css Audio - Active file-generic CSS - Active Generic - Active HTML - Active JS - Active SVG - Active Text - Active file-generic Video - Active header Love html icon-new-collection icon-person icon-team numbered-list123 pop-out spinner split-screen star tv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              mixin piece()
  .piece
    .bottom
    .middle
    .top  

mixin pieces()
  - for (var i = 0; i < 16; i++)
    +piece

mixin cell(column, row)
  each properties in ["square short dark hole", "square tall light hole", "square short light hole", "square tall dark hole", "square short dark solid", "square tall light solid", "square short light solid", "square tall dark solid", "round short dark solid", "round tall light solid", "round short light solid", "round tall dark solid", "round short dark hole", "round tall light hole", "round short light hole", "round tall dark hole"]
  
    input(type='radio' name='r' + row + 'c' + column class='r' + row + 'c' + column + ' ' + properties)
  
  .space(class='r' + row + 'c' + column)
    +pieces

mixin caps()
  - for (var i = 0; i < 16; i++)
    .cap

.game

  form

    - for (var i = 0; i < 16; i++)
      input(type='radio' name='selection')

    button.info Info
    
    .instructions
      p Both Players take turns choosing a piece which the other player must then place on the board. A player wins by placing a piece on the board which forms a horizontal, vertical, or diagonal row of four pieces, all of which have a common attribute (all short or tall, all circle or square, all light or dark, all solid on top or hole on top).
      .close Click anywhere to close info.

    .lineup
      +pieces
    
    .board
      
      - for (var row = 1; row <= 4; row++)
        - for (var column = 1; column <= 4; column++)
          +cell(column, row)
      
      .game-end
        .text Player <span class="winner"></span> wins!
      
      .directions
        .select Player <span class="winner"></span><br/>Select a piece
        .place Player <span class="turn"></span><br/>Place your piece
      
      .caps
        +caps
      
      .caps2
        +caps
      
      h1 Quarto
      
      button(type='reset') Reset
            
          
!
            
              $properties: 'square', 'round', 'short', 'tall', 'dark', 'light', 'hole', 'solid'

.game
  counter-reset: turn 1 winner 2
  height: 100vh
  width: 100vw
  display: flex
  align-items: center
  justify-content: center
  font-size: 0
  overflow: hidden
  background: linear-gradient(45deg, rgba(104,122,165,1) 0%,rgba(101,145,155,1) 100%)

form
  position: relative
  transform: rotate(45deg) skew(-15deg, -15deg)
  mix-blend-mode: overlay


  
  
// Game Name

h1
  position: absolute
  right: 100%
  bottom: 0
  font-size: 48px
  color: #707070
  transform: rotate(-90deg) translateX(120px)
  transform-origin: right bottom


  
  
// Buttons

button
  position: absolute
  z-index: 10
  left: 262px
  top: -130px
  width: 50px
  line-height: 50px
  padding: 0
  font-size: 12px
  text-align: center
  background: #fff
  border: none
  outline: none
  cursor: pointer
  transform: translate3d(0,0,0)
  transition: 200ms
  opacity: 0.25

  &:hover
    opacity: 1 !important

  &[type="reset"]
    visibility: hidden
    z-index: 12
  
  &.info
    left: auto
    right: 140px
    
    &:focus
      opacity: 0
      pointer-events: none
      
      & ~ .board .piece
        opacity: 0 !important
      
      & + .instructions
        visibility: visible
        opacity: 1
      
      & ~ .board .directions
        opacity: 0 !important

.board input:checked ~ button[type="reset"],
  visibility: visible
  opacity: 0.25

  
  

// Instructions

.instructions
  position: absolute
  z-index: 11
  left: 0
  right: 0
  top: 0
  bottom: 0
  background: #808080
  font-size: 16px
  -webkit-font-smoothing: antialiased
  -moz-osx-font-smoothing: grayscale
  line-height: 1.75rem
  color: #ffffff
  padding: 10%
  visibility: hidden
  opacity: 0
  transition: 500ms

  &::before
    content: ''
    position: absolute
    left: -9999px
    right: -9999px
    top: -9999px
    bottom: -9999px

  .close
    text-align: center
    margin-top: 30px
    color: #505050


    
    
// Piece Lineup

input[name="selection"]
  position: absolute
  left: 400px
  top: 400px
  z-index: 5
  display: inline-block
  margin: 0
  cursor: pointer
  width: 50px
  height: 50px
  opacity: 0

.lineup
  position: absolute
  z-index: 1
  left: -25px
  top: -25px
  pointer-events: none

  .piece
    position: absolute
    left: 400px
    top: 400px
    width: 100px
    height: 100px
    opacity: 0.4
    transform: scale(-0.3333) rotate(-180deg) !important
    transition: 200ms

// Increase opacity for selection hover and checked
@for $i from 1 through 16
  input[name="selection"]:nth-child(#{$i})
    &:hover ~ .lineup .piece:nth-child(#{$i}),
    &:checked ~ .lineup .piece:nth-child(#{$i})
      opacity: 1

// Selection position includes cap positioning
@for $i from 1 through 8
  input[name="selection"]:nth-child(#{$i}),
  .cap:nth-child(#{$i}),
  .lineup .piece:nth-child(#{$i})
    left: ($i - 1) * 50px

@for $i from 1 through 8
  input[name="selection"]:nth-child(#{$i + 8}),
  .cap:nth-child(#{$i + 8}),
  .lineup .piece:nth-child(#{$i + 8})
    top: 350 - ($i - 1) * 50px

input[name="selection"]:checked ~ .board
  pointer-events: all


  
  
// Selection Caps

.caps,
.caps2
  position: absolute
  z-index: 5
  left: 0
  top: 0
  pointer-events: none

.cap
  position: absolute
  left: 400px
  top: 400px
  width: 50px
  height: 50px
  pointer-events: none
  transition: 300ms
  

  
  
// Selection Logic

@for $i from 1 through 16
  
  // Raise the z-index of all board inputs corresponding to the selected piece
  input[name="selection"]:nth-child(#{$i}):checked ~ .board > input:nth-child(17n - #{17 - $i})
    z-index: 2

  // Add cap to the selection of a placed piece so player can no longer select it
  .board input:nth-child(17n - #{17 - $i}):checked ~ .caps .cap:nth-child(#{$i})
    pointer-events: all
    background: #808080
  
  // Add caps to all non-selected pieces so player can't change selection after it's made
  input[name="selection"]:nth-child(#{$i}):focus ~ .board .caps2 .cap:not(:nth-child(#{$i}))
    pointer-events: all
    background: #808080
    opacity: 0.5




// Board

.board
  position: relative
  width: 400px
  height: 400px
  pointer-events: none

  &::before
    content: ''
    position: absolute
    left: 1px
    right: 1px
    top: 1px
    bottom: 1px
    border: 1px solid #fff

  & > input[type='radio']
    position: absolute
    z-index: 1
    margin: 0
    cursor: pointer
    width: 25%
    height: 25%
    opacity: 0

.space
  position: relative
  display: inline-block
  width: 100px
  height: 100px
  text-align: center
  line-height: 100px
  border: 1px solid #fff
  box-sizing: border-box
  transition: 120ms
  pointer-events: none

@for $row from 1 through 4
  @for $column from 1 through 4
    
    // Place all board inputs
    .board > input.r#{$row}c#{$column}
      left: ($column - 1) * 25%
      top: ($row - 1) * 25%
    
    // Raise the z-index of a used space to prevent the inputs from being clicked
    input.r#{$row}c#{$column}:checked ~ .space.r#{$row}c#{$column}
      z-index: 4
      pointer-events: all
    
    // Highlight spaces when hovering over them
    input[name="selection"]:checked ~ .board > input.r#{$row}c#{$column}:hover ~ .space.r#{$row}c#{$column}
      background: rgba(255,255,255,0.2)


    @for $i from 1 through 16
    
      // Place a cap over the board when a piece is placed so the player can't place another of the same type
      input[name="selection"]:nth-child(#{$i}):checked ~ .board > input:nth-child(17n - #{17 - $i}).r#{$row}c#{$column}:checked ~ .space.r#{$row}c#{$column}::before,
        content: ''
        position: absolute
        z-index: 3
        pointer-events: all
        left: calc(-300% - 8px)
        right: calc(-300% - 8px)
        top: calc(-300% - 8px)
        bottom: calc(-300% - 8px)

      // Permanently show a placed piece
      .board > input:nth-child(17n - #{17 - $i}).r#{$row}c#{$column}:checked ~ .space.r#{$row}c#{$column} .piece:nth-child(#{$i})
        opacity: 1




// Game Pieces
  
.piece
  position: absolute
  z-index: 6
  left: 0
  right: 0
  top: 0
  bottom: 0
  opacity: 0
  font-size: 1rem
  cursor: default
  pointer-events: none
  transform: translate(-20px,-20px)
  transition: 400ms

.piece .bottom,
.piece .middle,
.piece .top
  position: absolute
  left: 25%
  top: 25%
  width: 50%
  height: 50%
  border: 2px solid #fff
  box-sizing: border-box
  background: #c0c0c0

.piece:nth-child(n + 9) .bottom,
.piece:nth-child(n + 9) .top
  border-radius: 50%

.piece .bottom
  transform: translate(20px,20px)

.piece .middle
  border-width: 0 2px
  transform: rotate(-45deg) scaleY(1.2)

.piece .top
  transform: translate(-20px,-20px)

// Tall pieces
.piece:nth-child(even)
  transform: translate(-40px,-40px)

.piece:nth-child(even) .bottom
  transform: translate(40px,40px)

.piece:nth-child(even) .top
  transform: translate(-40px,-40px)

.piece:nth-child(even) .middle
  transform: rotate(-45deg) scaleY(2.2)

// Circle Pieces
.piece:not(:nth-child(n + 9)) .middle
  transform: rotate(-45deg) scaleX(1.4) scaleY(1.2)

.piece:not(:nth-child(n + 9)):nth-child(even) .middle
  transform: rotate(-45deg) scaleX(1.4) scaleY(2.3)

.piece:not(:nth-child(n + 9)) .middle::before
  content: ""
  position: absolute
  left: 50%
  top: 0
  bottom: 0
  border-left: 2px solid #fff
  margin-left: -1px
  transform: translateY(52%)

.piece:not(:nth-child(n + 9)):nth-child(even) .middle::before
  transform: translateY(28%)

// Dark Pieces
.piece:nth-child(4n) .bottom,
.piece:nth-child(4n + 1) .bottom,
.piece:nth-child(4n) .middle,
.piece:nth-child(4n + 1) .middle,
.piece:nth-child(4n) .top,
.piece:nth-child(4n + 1) .top
  background: #404040

// Light Pieces
.piece:nth-child(-n+4) .top::before,
.piece:nth-last-child(-n+4) .top::before
  content: ""
  position: absolute
  left: 7px
  right: 7px
  top: 7px
  bottom: 7px
  border: 2px solid #fff
  border-radius: 50%
  background: rgba(0,0,0,0.1)


  

// Game End Logic

.winner::before
  content: counter(winner)

.game-end
  position: fixed
  z-index: 6
  left: -60px
  right: -60px
  top: -60px
  bottom: -60px
  background: #808080
  color: #FFF
  visibility: hidden
  opacity: 0
  display: flex
  align-items: center
  justify-content: center
  
  .text
    position: absolute
    transform: rotate(-45deg) scaleY(1.7)
    transition: 200ms

@each $property in $properties
  @for $row from 1 through 4
    .#{$property}.r#{$row}c1:checked ~ .#{$property}.r#{$row}c2:checked ~ .#{$property}.r#{$row}c3:checked ~ .#{$property}.r#{$row}c4:checked ~ .game-end
      visibility: visible
      opacity: 0.8
      font-size: 28px
      transition: 200ms
      transition-delay: 200ms
      & ~ .directions
        opacity: 0 !important
  @for $column from 1 through 4
    .#{$property}.r1c#{$column}:checked ~ .#{$property}.r2c#{$column}:checked ~ .#{$property}.r3c#{$column}:checked ~ .#{$property}.r4c#{$column}:checked ~ .game-end
      visibility: visible
      opacity: 0.8
      font-size: 28px
      transition: 200ms
      transition-delay: 200ms
      & ~ .directions
        opacity: 0 !important
  .#{$property}.r1c1:checked ~ .#{$property}.r2c2:checked ~ .#{$property}.r3c3:checked ~ .#{$property}.r4c4:checked ~ .game-end,
  .#{$property}.r1c4:checked ~ .#{$property}.r2c3:checked ~ .#{$property}.r3c2:checked ~ .#{$property}.r4c1:checked ~ .game-end
    visibility: visible
    opacity: 0.8
    font-size: 28px
    transition: 200ms
    transition-delay: 200ms
    & ~ .directions
      opacity: 0 !important




// Turns

.turn::before
  content: counter(turn)

.directions
  position: absolute
  right: 204px
  top: -118px
  white-space: nowrap
  text-align: right
  background: #808080
  font-size: 16px
  color: #CCC
  transition: opacity 200ms
  
  .select
    display: block
  
  .place
    display: none

input[name="selection"]:focus ~ .board .select,
.board > input:active ~ .directions .select
  display: none

input[name="selection"]:focus ~ .board .place,
.board > input:active ~ .directions .place
  display: block
    
.board > input:checked,
.board > input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked
  counter-increment: turn 1 winner -1

.board > input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked,
.board > input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked ~ input:checked
  counter-increment: turn -1 winner 1
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................

Console