Anders Tornblad

All about the code

Label archive for css

Using Source Maps with CSS

StackOverflow user Rob had a problem inspecting his SASS stylesheets after having them preprocessed by Codekit.

Having set the Output Style to "Compressed", the resulting CSS stylesheets were optimized and minified, making it almost impossible to trace the CSS back to the original SASS files.

Checking the Create a Source Map setting allowed him to help Google Chrome DevTools map the compiled CSS to the original SASS files, using a .map file, that the browser automatically uses. The principle of Source Maps is well known for JavaScript developers, but most people don't know that it is possible for CSS preprocessors too.

More information is available in the Codekit documentation for SASS.

FizzBuzz in CSS

One recurring complaint among experienced programmers is that there are lots of junior talent that could not even implement a simple FizzBuzz program. One blog article that started it off was Using FizzBuzz to Find Developers who Grok Coding, written in 2007 by Imran Ghory, and after Jeff Atwood wrote about it, literally hundreds of programmers wanted to prove their value by writing FizzBuzz solutions in every conceivable way and in every language available.

Just for fun, I tried writing a pure CSS solution, just like my pure CSS "Hello World" solution, but unfortunately, I couldn't. No matter how I try, I still have to add 100 P elements to the HTML document. But once that is done, the solution is really simple.

body { counter-reset: i } p { counter-increment: i; } p:before { content: counter(i) } p:nth-child(5n):before { content: '' } p:nth-child(3n):before { content: 'Fizz' } p:nth-child(5n):after { content: 'Buzz' }

This use of CSS is not as unorthodox as with Hello World, but it's still very convoluted. But then again, the FizzBuzz challenge is a pretty convoluted way of putting interviewees to the test.

Oh, and I made a pen for you.

A simple hamburger button

There are lots of tutorials, pens and fiddles out there describing how to create the perfect hamburger button, as well as a few bloggers telling us to stop using it. Me, I kind of like it, actually. It has become a household item – most people know what it is and what it should do. Also, it has been around for almost 40 years. Check out this history of widgets until 1990

A simple layout

I like trying to keep things as simple as possible, so instead of going all in with SVG, JavaScript, animations and complicated transitions, the HTML markup for my hamburger button is simple:

<button class="hamburger"> <hr> <hr> <hr> </button>

The CSS is almost as simple:

button.hamburger { display: flex; flex-direction: column; justify-content: space-around; align-items: stretch; width: 6vw; height: 6vw; box-sizing: border-box; padding: 1vw; border-raius: 0.8vw; background: #195024; cursor: pointer; } button.hamburger hr { display: block; border: 0; height: 0.5vw; background: white; }

Always some browser issue

This worked like a charm until I tested in Firefox. Even though the button element has justify-content: space-around, the hr elements get lumped together in the middle. Even IE got it right. But just for Firefox, I had to add this to my CSS:

button.hamburger hr + hr { margin-top: 0.5vw; }

Revisiting CssFlip

When I first started experimenting with modern Web APIs, 3D transforms was still an experimental feature. Browser support was limited and shaky, and required vendor prefixes. These days support is much better, but there are still a lot of quirks when it comes to browser implementation.

Back in 2011, I wrote a demo called CSS Page Flip, using a combination of CSS and some JavaScript to let a user flip through pages in a book. The transitions are declared in CSS and are triggered by JavaScript. Pages on the left have their transform-origin set to their right edge, which is aligned to the horizontal center of the screen, while pages on the right have their transform-origin set to their left edge. By applying backface-visibility: hidden, I can then rotate pages along the Y axis for a pretty simple effect.

#book { perspective: 2000px; transform-style: preserve-3d; } .page { width: 50%; height: 100%; position: absolute; top: 0px; left: 0px; margin-left: 50%; overflow: hidden; transform-style: flat; backface-visibility: hidden; transition: none; transform: none; } .page:first-child { margin-left: 0px; transform-origin: right center; } .page:last-child { transform-origin: left center; } .currentFold.forward > .page:last-child { transform: rotateY(0deg); } .nextFold.forward > .page:first-child { transform: rotateY(179.9deg); } .currentFold.backward > .page:first-child { transform: rotateY(0deg); } .nextFold.backward > .page:last-child { transform: rotateY(-179.9deg); } .folding .page { transition: all 1s ease-in-out; } .folding > .currentFold.forward > .page:last-child { transform: rotateY(-179.9deg); } .folding > .nextFold.forward > .page:first-child { transform: translateZ(1px) rotateY(0deg); } .folding > .currentFold.backward > .page:first-child { transform: rotateY(179.9deg); } .folding > .nextFold.backward > .page:last-child { transform: translateZ(1px) rotateY(0deg); }

It took a lot of fiddling to find good values for rotateY(). Almost every new version of Webkit broke my experiment, but I eventually settled on a combination of 0deg, -180deg and 180deg.

CSS Flip in EdgeEdge behaving badly A couple of years later, the major browsers started supporting 3D transforms, even without vendor prefixes. Unfortunately all of them have different ideas about how to transition from 180deg or -180deg to 0deg. Finally I thought of forcing the browsers to do what I want by having -179.9deg and 179.9deg. This works fine now, unless for (of course) IE and Edge. IE doesn't even support 3D transforms correctly without prefix, and for some reason Edge treats the transformation matrix differently than the other browsers, completely breaking part of the animation.

Apart from the page flipping, the demo also has an automatic page layout mechanism that reflows the chapters and the text blocks when needed. In the original demo, the contents of the book was actually a detailed description of how the demo was made, but unfortunately the original content was lost at some point. Now it is my personal story instead. Enjoy!

During the next week or two, I will make an effort to bring the solution forward into the 2016 state of mainstream browsers, including the following:

  • Fix scroll wheel flipping in Firefox
  • Handle chapter navigation using history.pushState()
  • Add some interactive stuff on some of the pages
  • Some effort of fixing the weird behavior in Microsoft Edge
  • Minimal effort of making it work in Microsoft IE

When that is done, I will open-source the whole thing on GitHub.

Almost pure CSS page flip

Google Chrome still has a long way to go when rendering stuff that is a just little bit more advanced. Experimenting with CSS3 3D Transforms.

I placed a video element on a div element that rotates in 3D using CSS3 3D Transforms and CSS3 Transitions. In Safari, everything renders smoothly, even when the video is playing! In Chrome (I’m using Google Chrome 9 Beta), the entire div containing the video disappears while the transition is running.

That experiment led to more experimenting, and suddenly I had a fully functioning page flipping effect – almost purely done in CSS. Using a simple combination of -webkit-tranform-origin and -webkit-transform went a very long way.

Actually, the contents of the project explains itself. If you are using Google Chrome or Desktop Safari on Windows or Mac, use the scroll wheel to flip through pages, or click on a page. If you are on an iOS device, flick a page to go forward or backward.

Please note! This works best on Safari and on iOS devices. Google Chrome does support CSS 3D Transforms, but only if you actively enable it. Type about:flags into the address bar of your Google Chrome browser, and click Enable for GPU Accelerated Compositing to enable 3D CSS in Chrome, then restart the browser.

The experiment is called CSS Flip. Please try it out now on and tell me what you think.