09 Apr 2013

Just like last year, this post is an reduced version of the talk by the inimitable Lea Verou with inline demo's. It's based on the video recording of her talk and her slides.

Center floating block without wrapper

It's an extremely common situation to want to center float your content in a fixed width column. The usual solution would be to make a full width wrapper element for your content and style it like this:

.content-wrapper {
   width: 100%;
}
.content {
   margin: 0 auto;
   width: 200px;
}


I'm sure making this wrapper everytime has bothered you as much as me and with the introduction of calc() for CSS, it can be left out! Just use:



.content {
   padding: 1em calc(50% - 100px;)
}


The 1em can be anything, since it is the vertical padding. The 100px is half of the intended width. What you're effectively expressing here is a full width element (default for all display: block; elements) with a left and right padding of 50% of the screen, but subtracting (half of) the width of the (virtual in this case) content column. This is the single most useful application of mixed unit calculations in runtime CSS, IMHO. It even works in IE9+.



Example:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer id semper turpis. Donec convallis sollicitudin magna ut fermentum. Vestibulum nec diam sit amet velit gravida euismod. Maecenas rutrum nisi ut tortor mollis volutpat. Nullam lacus leo, sodales eget viverra ac, hendrerit tristique dui. Vivamus semper adipiscing fermentum. Phasellus ultricies vestibulum velit id ullamcorper. Maecenas cursus velit et nunc placerat lacinia. In vitae leo mi, eu scelerisque nibh. Praesent lacinia leo sit amet dui ullamcorper non posuere neque consequat. Nam ac adipiscing massa. Sed eu massa vitae nibh mollis varius. Vestibulum ut felis eget felis tincidunt porttitor at nec eros. Aliquam in hendrerit purus. Donec vehicula congue iaculis.


Multiple transitions

Already 2 years back I have mentioned CSS transitions, but now it is possible to append multiple transitions. Let's put it into practice using my old example:

Try hovering over this text.
#transition {
  border: 2px dotted #fff;
  height: 20px;
  overflow: hidden;
  transition-duration: 1s;
  -o-transition-duration: 1s;
  width: 200px;
}
#transition:hover {
  height: 310px;
  width: 100%;
}

As you can see, upon hover the box expands in the horizontal and vertical direction evenly and at the same time. Now it is possible to combine transitions, we can expand it first in width and then roll it out vertically. It works in IE, but only 10+.

Now, who dares hovering?!
#transition2 {
  border: 2px dotted #fff;
  height: 20px;
  overflow: hidden;
  transition: 1s width, 
                   1s 1s height, 
                   1s 2s background, 
                   1s 2s color,
                   1s 2s border;
  /* the 1s directly before height is the delay 
       for the second animation */
  width: 200px;
}
#transition2:hover {
  background: #ccc;
  border: 2px dotted #000;
  color: #000;
  height: 460px;
  width: 100%;
}

This example reverts the animation the same way as it starts: first width then height. It is possible to do this backwards, but it would involve adding a class (e.g. current) with javascript after the animation ends and then overwriting the transition property to go backwards.



Scaling line backgrounds

Using CSS it is possible to set a separate background for alternating lines of text, without adding HTML elements for every line. This might be comfortable for displaying source code:

.zebra {
  background-image: linear-gradient(#000 50%, #333 50%);
  background-origin: content-box;
  background-size: 100% 2.4em;
  color: #ff8100;
  font-family: monospace;
  line-height: 1.2em;
}

Let's go into this in a little more detail. A linear-gradient as background and the background-size property where also used in my previous article to display diagonally striped backgrounds. The gradient uses 2 colors stops both at 50%, making two solid planes in the desired colors. Next, the background-size is set to 100% of the width but 2.4em, i.e. twice the line-height. This makes the background pattern of the two solid planes repeat every two lines. This is why it is essential that the background height is twice the line-height.

As if this wasn't already briljant enough, it also automatically scales with the font-size. Because the background-size and line-height use the relative unit em, they both scale with the font-size. Try changing it:



A speech bubble

What is a speech bubble without the tail pointing to its speaker? Well, just a bubble, I suppose. It is also a commonly used UI component to give information about some part of the UI, e.g. information for a specific input field. Most UI design I've seen use CSS for the bubble but an image for the tail, but it is possible to do this in pure CSS, and it is surprisingly easy.

Imagine we want to make our tail point up. Let's first define a div with zero height but fat borders. I'll give the bottom border a different color:

We just make the top border zero height:
And then all the borders, except for the bottom, transparent:
Adding this as a pseudo element to the actual bubble, gives us this:



Enter your name here:
Really, you need me to explain what "Enter your name here" means?
.bubble4 {
  background: #ccc;
  border-radius: 5px;
  color: #000;
  padding: 10px;
  position: relative;
}
.bubble4:before {
  border: 30px solid transparent;
  border-top: 0px solid transparent;
  border-bottom: 30px solid #ccc;
  content: ""; 
  height: 0;
  left: 190px;
  position: absolute;
  top: -30px;
  width: 0;
}



Normally, adding a box-shadow to this speech bubble, would leave the tail "unshadowed":



Enter your name here:
Really, you need me to explain what "Enter your name here" means?
.bubble-shadow1 {
  box-shadow: 1px -2px 5px #8DB11F;
}



A new CSS property, filter, should be able to help here. It adds SVG filters to CSS. This doesn't work as well in FF as it does in webkit. Although there is a workaround, the clean solution I present here only works in webkit.



Enter your name here:
Really, you need me to explain what "Enter your name here" means?
.bubble-shadow2 {
  -moz-filter: drop-shadow(1px -2px 5px #8DB11F);
  -ms-filter: drop-shadow(1px -2px 5px #8DB11F);
  -webkit-filter: drop-shadow(1px -2px 5px #8DB11F);
  filter: drop-shadow(1px -2px 5px #8DB11F);
}