cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

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.

Quick-add: + add another resource

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.

Quick-add: + add another resource

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.

            
              <main class="game">
  <div class="game__background"></div>
  <div class="game__foreground">
    <div class="foreground__mario"></div>
    <div class="foreground__ground"></div>
  </div>
</main>
            
          
!
            
              /**
 * Super Mario World in CSS
 *
 * Disclaimer: It works fine in Chrome 64 on MacOS. Firefox runs it 
 * properly too, but a bit slowly. In Safari, unfortunately, it  
 * simply doesn’t work at all, and I’m out of patience and time to 
 * debug it for now. I didn’t test it with other browsers or 
 * devices.
 *
 * 100% CSS:
 * - Only CSS gradients magic!
 * - No JavaScript
 * - No embedded images/data URIs
 * - No external images 
 * - Using a microscopic HTML =)
 *
 * Follow me:
 *   twitter.com/alcidesqueiroz
 *   github.com/alcidesqueiroz  
 *   medium.com/@alcidesqueiroz
 *   email: alcidesqueiroz <at> gmail
 */

// # Background forest palette
$bg-green-color--dark = #1E6910;
$bg-green-color--medium = #3F7914;
$bg-green-color--light = #5F8918;
$bg-green-color--lightest = #86A11E;

// # Foreground palette
// ## Bush colors
$fr-green-color--light = #00CA28;
$fr-green-color--dark = #008116;

// ## Ground colors
$ground-color-1 = #C7985B;
$ground-color-2 = #DEC058;
$ground-color-3 = #77681F;

// # Mario palette
$ct = transparent;
$c1 = #4E0000;
$c2 = #F7386F;
$c3 = #F5D775;
$c4 = #AF215F;
$c5 = #D6A040;
$c6 = #FFFFFF;
$c7 = #000000;
$c8 = #F7D0C1;
$c9 = #F56C67;
$ca = #87571D
$cb = #272F86;
$cc = #438097;
$cd = #81D9C9;

// Dimensions
$total-width = 80rem;
$mario-sprite-width = 15;

// # Global lists used to accumulate gradients
// ## Gradients used to render the forest
$forest-bg-gradients = ();
$forest-bg-sizes = ();
$forest-bg-positions = ();

// ## Gradients used to render the bushes
$bush-gradients = ();
$bush-sizes = ();
$bush-positions = ();

// Draws a pixelated sprite by using multiple linear gradients
draw-sprite($lines...) {
  // Lists used to accumulate gradients and their positions
  $mario-gradients = ();
  $mario-positions = ();

  // Calculates the appropriate size for each gradient stop
  $increment = 100 / $mario-sprite-width;
  $line-index = 0;

  // Iterates over the lines collection
  for $line in $lines {
    $percent = 0;
    $gradient = ();
    push($mario-positions, (0 $line-index * 0.2rem));

    for $pixel in $line {
      push($gradient, join('', $pixel ' ' $percent '%'));
      $percent += $increment;
      push($gradient, join('', $pixel ' ' $percent '%'));
    }

    // Pushes the finished linear-gradient to the gradients list
    push($mario-gradients, unquote('linear-gradient(to right, ' + join(', ', $gradient) + ')'));
    $line-index += 1;
  }

  // Assigns the accumulated value to their respective props
  background-image: unquote(join(', ', $mario-gradients));
  background-position: unquote(join(', ', $mario-positions));
}

// Mixin for rendering the first Mario sprite by using multiple linear-gradients
mario-sprite-1() {
  draw-sprite(
    ($ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct),
    ($ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct),
    ($ct $ct $ct $ct $ct $ct $c1 $c1 $c1 $c1 $c1 $ct $ct $ct $ct),
    ($ct $ct $ct $ct $c1 $c1 $c2 $c2 $c2 $c3 $c2 $c1 $ct $ct $ct),
    ($ct $ct $ct $c1 $c2 $c2 $c4 $c4 $c5 $c3 $c6 $c1 $ct $ct $ct),
    ($ct $ct $c1 $c4 $c2 $c4 $c4 $c7 $c7 $c7 $c7 $c7 $c7 $ct $ct),
    ($ct $c1 $c4 $c4 $c4 $c7 $c7 $c7 $c7 $c7 $c7 $c7 $c7 $c7 $ct),
    ($ct $c1 $c8 $c7 $c7 $c7 $c9 $c7 $c9 $c7 $c9 $ct $ct $ct $ct),
    ($c1 $c8 $ca $c8 $c7 $c9 $c8 $c7 $c8 $c7 $c8 $ca $ca $ct $ct),
    ($c1 $c9 $ca $c8 $c7 $c7 $c8 $c8 $c8 $c8 $c8 $c8 $c8 $ca $ct),
    ($c1 $c7 $c9 $c8 $c7 $c8 $c8 $c7 $c9 $c9 $c9 $c9 $c9 $ca $ct),
    ($ct $c7 $c7 $c9 $c9 $c8 $c7 $c7 $c7 $c7 $c7 $c7 $c7 $ct $ct),
    ($ct $ct $c7 $ca $c9 $c9 $c9 $c9 $c7 $c7 $c7 $c7 $ct $ct $ct),
    ($ct $ct $ca $c4 $ca $ca $ca $ca $ca $cb $ct $ct $ct $ct $ct),
    ($ct $ct $ca $c4 $c4 $c2 $ca $cc $cd $cd $cb $ct $ct $ct $ct),
    ($ct $c7 $ca $c6 $c6 $c6 $ca $c6 $c6 $cd $c6 $cb $c7 $c7 $ct),
    ($c7 $ca $ca $c6 $c6 $ca $cc $c6 $c6 $cd $c6 $c7 $c3 $c7 $c7),
    ($c7 $ca $ca $c6 $c6 $ca $cc $cc $cc $cd $cb $c7 $ca $c7 $c7),
    ($c7 $ca $cb $ca $ca $cc $cc $cc $cc $cb $c7 $ca $c7 $c7 $ct),
    ($c7 $ca $c3 $c7 $ct $cb $cb $cb $cb $ct $c7 $ca $c7 $c7 $ct),
    ($ct $c7 $c7 $ct $ct $ct $ct $ct $ct $ct $ct $c7 $c7 $ct $ct),
    ($ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct)
  );
}

// Mixin for rendering the second Mario sprite by using multiple linear-gradients
mario-sprite-2() {
  draw-sprite(
    ($ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct),
    ($ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct),
    ($ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct $ct),
    ($ct $ct $ct $ct $ct $ct $c1 $c1 $c1 $c1 $c1 $ct $ct $ct $ct),
    ($ct $ct $ct $ct $c1 $c1 $c2 $c2 $c2 $c3 $c2 $c1 $ct $ct $ct),
    ($ct $ct $ct $c1 $c2 $c2 $c4 $c4 $c5 $c3 $c6 $c1 $ct $ct $ct),
    ($ct $ct $c1 $c4 $c2 $c4 $c4 $c7 $c7 $c7 $c7 $c7 $c7 $ct $ct),
    ($ct $c1 $c4 $c4 $c4 $c7 $c7 $c7 $c7 $c7 $c7 $c7 $c7 $c7 $ct),
    ($ct $c1 $c8 $c7 $c7 $c7 $c9 $c7 $c9 $c7 $c9 $ct $ct $ct $ct),
    ($c1 $c8 $ca $c8 $c7 $c9 $c8 $c7 $c8 $c7 $c8 $ca $ca $ct $ct),
    ($c1 $c9 $ca $c8 $c7 $c7 $c8 $c8 $c8 $c8 $c8 $c8 $c8 $ca $ct),
    ($c1 $c7 $c9 $c8 $c7 $c8 $c8 $c7 $c9 $c9 $c9 $c9 $c9 $ca $ct),
    ($ct $c7 $c7 $c9 $c9 $c8 $c7 $c7 $c7 $c7 $c7 $c7 $c7 $ct $ct),
    ($ct $ct $c7 $ca $ca $c9 $c9 $c9 $c7 $c7 $c7 $c7 $ct $ct $ct),
    ($ct $ct $ct $c1 $c4 $ca $ca $ca $ca $cb $ct $ct $ct $ct $ct),
    ($ct $ct $c1 $c4 $c4 $c2 $cc $cc $cd $cd $cb $ct $ct $ct $ct),
    ($ct $ct $c1 $c6 $c6 $c6 $ca $c6 $c6 $cd $c6 $cb $ct $ct $ct),
    ($ct $ct $ca $c6 $c6 $ca $cc $c6 $c6 $cd $c6 $cb $ct $ct $ct),
    ($ct $ct $ca $c6 $c6 $ca $cc $cc $cc $cd $cd $cb $ct $ct $ct),
    ($ct $ct $ca $c6 $c6 $ca $cc $cc $cb $cc $cb $ct $ct $ct $ct),
    ($ct $ct $ct $ca $ca $ca $ca $c7 $ca $c7 $ct $ct $ct $ct $ct),
    ($ct $ct $ct $c7 $ca $ca $ca $c3 $c7 $c3 $c7 $ct $ct $ct $ct),
    ($ct $ct $ct $c7 $c7 $c7 $c7 $c7 $c7 $c7 $c7 $ct $ct $ct $ct)
  );
}

// Appends a new gradient to the forest gradients list
append-to-forest-gradient($branch, $grad) {
  append-to-gradient(
    $branch,
    $grad,
    $forest-bg-gradients,
    $forest-bg-sizes,
    $forest-bg-positions);
}

// Appends a new gradient to the bushes gradients list
append-to-bush-gradient($branch, $grad) {
  append-to-gradient(
    $branch,
    $grad,
    $bush-gradients,
    $bush-sizes,
    $bush-positions);
}

// Appends a gradient to the supplied list
append-to-gradient($branch, $grad, $gradients, $sizes, $positions) {
  push($gradients, unquote($grad));
  push($sizes, $branch.size != null ? unquote($branch.size) : unquote('5rem 5rem'));
  push($positions, unquote($branch.position));
}

// Renders the forest by using multiple radial-gradient backgrounds
forest-background($branches...) {
  $branch = arguments if length(arguments) > 1;

  // Front part of a foreground tree branch
  for $branch in $branches {
    if (!$branch.secondary) {
      append-to-forest-gradient($branch, 'radial-gradient(closest-side, ' + $bg-green-color--dark + ' 0%, ' + $bg-green-color--dark + ' 77%, transparent 78%)');
    }
  }

  // First shadow of a foreground tree branch
  for $branch in $branches {
    if (!$branch.secondary && !$branch.onlyFrontColor) {
      append-to-forest-gradient($branch, 'radial-gradient(closest-side, transparent 0%, transparent 70%, ' + $bg-green-color--medium + ' 78%, ' + $bg-green-color--medium + ' 89%, transparent 86%)');
    }
  }

  // Second shadow of a foreground tree branch
  for $branch in $branches {
    if (!$branch.secondary && !$branch.onlyFrontColor) {
      append-to-forest-gradient($branch, 'radial-gradient(closest-side, transparent 0%, transparent 85%, ' + $bg-green-color--light + ' 89%, ' + $bg-green-color--light + ' 100%, transparent 101%)');
    }
  }

  // Front part of a background tree branch
  for $branch in $branches {
    if ($branch.secondary) {
      append-to-forest-gradient($branch, 'radial-gradient(closest-side, ' + $bg-green-color--medium + ' 0%, ' + $bg-green-color--medium + ' 77%, transparent 78%)');
    }
  }

  // First shadow of a background tree branch
  for $branch in $branches {
    if ($branch.secondary && !$branch.onlyFrontColor) {
      append-to-forest-gradient($branch, 'radial-gradient(closest-side, transparent 0%, transparent 70%, ' + $bg-green-color--light + ' 78%, ' + $bg-green-color--light + ' 89%, transparent 86%)');
    }
  }

  // Second shadow of a background tree branch
  for $branch in $branches {
    if ($branch.secondary && !$branch.onlyFrontColor) {
      append-to-forest-gradient($branch, 'radial-gradient(closest-side, transparent 0%, transparent 85%, ' + $bg-green-color--lightest + ' 89%, ' + $bg-green-color--lightest + ' 100%, transparent 101%)');
    }
  }

  // Assigns the accumulated value to their respective props
  background-image: unquote(join(', ', $forest-bg-gradients));
  background-position: unquote(join(', ', $forest-bg-positions));
  background-size: unquote(join(', ', $forest-bg-sizes));
}

// Renders a foreground bush by using multiple radial-gradient backgrounds
foreground-bush($branches...) {
  $branch = arguments if length(arguments) > 1;

  // Front part of a foreground bush
  for $branch in $branches {
    if (!$branch.secondary) {
      append-to-bush-gradient($branch, 'radial-gradient(closest-side, ' + $fr-green-color--light + ' 0%, ' + $fr-green-color--light + ' 93%, transparent 94%)');
    }
  }

  // Border of a foreground bush
  for $branch in $branches {
    if (!$branch.secondary && !$branch.onlyFrontColor) {
      append-to-bush-gradient($branch, 'radial-gradient(closest-side, transparent 0%, transparent 93%, black 94%, black 100%, transparent 101%)');
    }
  }

  // Front part of a background bush
  for $branch in $branches {
    if ($branch.secondary) {
      append-to-bush-gradient($branch, 'radial-gradient(closest-side, ' + $fr-green-color--dark + ' 0%, ' + $fr-green-color--dark + ' 93%, transparent 94%)');
    }
  }

  // Border of a foreground bush
  for $branch in $branches {
    if ($branch.secondary && !$branch.onlyFrontColor) {
      append-to-bush-gradient($branch, 'radial-gradient(closest-side, transparent 0%, transparent 93%, black 94%, black 100%, transparent 101%)');
    }
  }

  // Assigns the accumulated value to their respective props
  background-image: unquote(join(', ', $bush-gradients));
  background-position: unquote(join(', ', $bush-positions));
  background-size: unquote(join(', ', $bush-sizes));
}

html{
  font-size: 62.5%;
}

  // The "Game" wrapper
  .game{
    height: 30rem;
    overflow: hidden;
    position: relative;
    width: 40rem;
  }

    // The background forest
    .game__background{
      animation: background-anim 7s linear 0s infinite;
      background-color: $bg-green-color--light;
      background-repeat: no-repeat;
      height: inherit;
      width: $total-width;

      // Passes the branches coordinates to the mixin responsible for rendering the background forest
      forest-background(
        { position: '-1rem 16rem' }, { position: '2rem 15rem' },
        { position: '5rem 16rem' }, { position: '8rem 17rem' },
        { position: '11rem 17rem' }, { position: '14rem 16rem' },
        { position: '17rem 14rem' }, { position: '19rem 13rem' },
        { position: '22rem 11rem' }, { position: '22rem 11rem' },
        { position: '25rem 11rem' }, { position: '28rem 12rem' },
        { position: '31rem 11rem' }, { position: '33rem 10rem' },
        { position: '36rem 9rem' }, { position: '39rem 10rem' },
        { position: '42rem 9rem' }, { position: '43rem 12rem' },
        { position: '46rem 13rem' }, { position: '49rem 14rem' },
        { position: '52rem 15rem' }, { position: '56rem 15rem' },
        { position: '58rem 13rem' }, { position: '59rem 11rem' },
        { position: '61rem 8rem' }, { position: '64rem 7rem' },
        { position: '67rem 6rem' }, { position: '70rem 5rem' },
        { position: '73rem 6rem' }, { position: '76rem 8rem' },

        { position: '8rem -2rem', secondary: true }, { position: '7rem 2rem', secondary: true },
        { position: '8rem 6rem', secondary: true }, { position: '9rem 8rem', secondary: true },
        { position: '12rem 8rem', secondary: true }, { position: '14rem 7rem', secondary: true },
        { position: '14rem 3rem', secondary: true }, { position: '14rem 0rem', secondary: true },
        { position: '13rem -2rem', secondary: true }, { position: '35rem -2rem', secondary: true },
        { position: '36rem 2rem', secondary: true }, { position: '35rem 5rem', secondary: true },
        { position: '50rem -2rem', secondary: true }, { position: '48rem 2rem', secondary: true },
        { position: '47rem 5rem', secondary: true }, { position: '47rem 9rem', secondary: true },
        { position: '65rem -2rem', secondary: true }, { position: '67rem 2rem', secondary: true },

        { position: '-20rem -10rem', size: '35rem 35rem', secondary: true, onlyFrontColor: true },
        { position: '0 7rem', size: '30rem 30rem', secondary: true, onlyFrontColor: true },
        { position: '12rem -10rem', size: '30rem 30rem', secondary: true, onlyFrontColor: true },
        { position: '45rem -5rem', size: '30rem 30rem', secondary: true, onlyFrontColor: true },
        { position: '10rem 11rem', size: '30rem 30rem', onlyFrontColor: true },
        { position: '-8rem 14rem', size: '30rem 30rem', onlyFrontColor: true },
        { position: '25rem 8rem', size: '30rem 30rem', onlyFrontColor: true },
        { position: '38rem 13rem', size: '30rem 30rem', onlyFrontColor: true },
        { position: '56rem 4rem', size: '30rem 30rem', onlyFrontColor: true }
      );
    }

    // Everything that happens in the foreground
    .game__foreground{
      // Parallax effect
      animation: foreground-anim 7s linear 0s infinite;

      bottom: 0;
      left: 0;
      position: absolute;
      right: 0;

      // Foreground bushes
      &:before, &:after{
        background-repeat: no-repeat;
        bottom: 5.1rem;
        content: '';
        display: block;
        height: 15rem;
        position: absolute;
        width: 25rem;

        // Passes the coordinates to the mixin responsible for rendering the foreground bushes
        foreground-bush(
          { position: '0 13rem', size: '3rem 3rem' },
          { position: '0 11rem', size: '3rem 3rem' },
          { position: '0 9rem', size: '3rem 3rem' },
          { position: '1rem 7rem', size: '3rem 3rem' },
          { position: '3rem 6rem', size: '3rem 3rem' },
          { position: '4rem 3.5rem', size: '3rem 3rem' },
          { position: '5rem 2rem', size: '3rem 3rem' },
          { position: '7rem 1rem', size: '3rem 3rem' },
          { position: '9rem 1.5rem', size: '3rem 3rem' },
          { position: '10rem 3rem', size: '3rem 3rem' },
          { position: '9.5rem 5rem', size: '3rem 3rem' },
          { position: '9rem 7.5rem', size: '3rem 3rem' },
          { position: '9rem 9.5rem', size: '3rem 3rem' },
          { position: '8.5rem 12rem', size: '3rem 3rem' },
          { position: '9rem 1rem', size: '3rem 3rem', secondary: true },
          { position: '11rem 2rem', size: '3rem 3rem', secondary: true },
          { position: '11.5rem 4rem', size: '3rem 3rem', secondary: true },
          { position: '11.5rem 6rem', size: '3rem 3rem', secondary: true },
          { position: '13rem 7rem', size: '3rem 3rem', secondary: true },
          { position: '15rem 8rem', size: '3rem 3rem', secondary: true },
          { position: '16rem 10rem', size: '3rem 3rem', secondary: true },
          { position: '15rem 12rem', size: '3rem 3rem', secondary: true },
          { position: '1rem 7rem', size: '10rem 10rem', onlyFrontColor: true },
          { position: '5rem 2rem', size: '7rem 7rem', onlyFrontColor: true },
          { position: '8rem 2rem', size: '6rem 6rem', secondary: true, onlyFrontColor: true },
          { position: '8rem 7rem', size: '10rem 10rem', secondary: true, onlyFrontColor: true }
        );
      }


      // Positionates the first bush
      &:before{
        left: 5rem;
      }

      // Positionates the second bush
      &:after{
        left: 60rem;
      }
    }

      // It's me, Mario!
      .foreground__mario{
        animation: mario-running 300ms linear 0s infinite;
        background-repeat: repeat-x;
        background-size: 100% 0.2rem;
        bottom: 5rem;
        height: 4.4rem;
        margin-left: 15rem;
        position: relative;
        width: 3rem;
        z-index: 1;
      }

      // The ground
      .foreground__ground{
        border-top: 0.1rem solid black;
        bottom: 0;
        height: 5rem;
        left: 0;
        position: absolute;
        width: $total-width;

        // The platform
        &:before{
          border-bottom-width: 0;
          border-radius: 1rem 1rem 0 0;
          border: 0.1rem solid black;
          bottom: 5rem;
          content: '';
          display: block;
          height: 7rem;
          left: 25rem;
          position: absolute;
          width: 30rem;
        }

        // Ground and platform
        &, &:before{
          background-color: $ground-color-1;
          background-image:
            radial-gradient(closest-side, $fr-green-color--light 0%, $fr-green-color--light 108%, $fr-green-color--dark 109%, transparent 110%),
            radial-gradient(closest-side, $fr-green-color--dark 0%, $fr-green-color--dark 114%, transparent 115%),
            radial-gradient(closest-side, $ground-color-2 0%, $ground-color-2 10%, transparent 11%),
            radial-gradient(closest-side, $ground-color-2 0%, $ground-color-2 10%, transparent 11%),
            radial-gradient(closest-side, $ground-color-2 0%, $ground-color-2 10%, transparent 11%),
            radial-gradient(closest-side, $ground-color-2 0%, $ground-color-2 10%, transparent 11%);
          background-position:
            0 -0.7rem,
            0 -0.4rem,
            0 0,
            1rem 2rem,
            1rem 2.5rem,
            2rem 4rem;
          background-repeat: repeat-x, repeat-x, repeat;
          background-size:
            1.5rem 1.5rem,
            1.5rem 1.5rem,
            2rem 2rem,
            2.5rem 2.5rem,
            3rem 3rem,
            4rem 4rem;
        }
      }

// Mario graceful running
@keyframes mario-running{
  0%, 49%{
    mario-sprite-1();
  }

  50%, 100%{
    mario-sprite-2();
  }
}

// Parallax magic
@keyframes background-anim{
  from{
    margin-left: 0;
  }

  to{
    margin-left: -20rem;
  }
}

// Foreground moving
@keyframes foreground-anim{
  from{
    padding-left: 0;
    margin-left: 0;
  }

  to{
    padding-left: 40rem;
    margin-left: -40rem;
  }
}

            
          
!
            
              // Nothing to see here... =P

/* 
  Follow me:
  twitter.com/alcidesqueiroz
  github.com/alcidesqueiroz  
  medium.com/@alcidesqueiroz
  email: alcidesqueiroz <at> gmail
*/
            
          
!
999px
Loading ..................

Console