CSS3

A practical introduction

By Lea Verou

Disclaimer
This slideshow was originally coded to run in Mozilla Firefox 4 beta or Minefield. Some features may not show properly in other browsers, such as CSS gradients or anything that depends on them.
about:me
A map of Europe, with Greece highlighted My company (fresset)
Isn’t CSS2.1 sufficient?

Question: What bugs you the most when coding CSS (2.1) today?

IMHO:

CSS3 attempts to solve these problems

Problem #1

Needing decorative images

Why is it a problem?
Translucent colors
The old way
Translucent colors
The CSS3 way
Translucent colors
The CSS3 way
And this is some text
RGBA, HSL, HSLA
Browser support*
Firefox
Full
support
Google Chrome
Full
support
Opera
Full
support
Apple Safari
Full
support
Internet Explorer
Full
support

* Assumes latest beta

Rounded corners
The old way
<div class="foo">
<div class="inner">
	<div class="inner2">
		<div class="inner3"></div>
	</div>
</div>
</div>
.foo {
background: url(img/corner_tr.png) top right no-repeat;
}
.foo .inner {
background: url(img/corner_br.png) bottom right no-repeat;
}
.foo .inner2 {
background: url(img/corner_tl.png) top left no-repeat;
}
.foo .inner3 {
background: url(img/corner_bl.png) bottom left no-repeat;
}
Rounded corners
The CSS3 way

border-radius: 20px

Rounded corners
The CSS3 way

border-radius: 40px / 20px

Rounded corners
The CSS3 way

border-radius: 40px 10px

Rounded corners
The CSS3 way

border-radius: 40px 50% 0

Rounded corners
The CSS3 way

border-radius: 40px 50% 0 10px

Note: There are also individual properties for that, e.g. border-top-left-radius

border-radius
Browser support*
Firefox
With
-moz-
Google Chrome
Full
support
Opera
Full
support
Apple Safari
Full
support
Internet Explorer
Full
support

* Assumes latest beta

Drop shadows
The old way
<div class="wrap1"><div class="wrap2">
  <div class="wrap3"><img src="object.gif" alt="The object casting a shadow" /></div>
</div></div>
.wrap1, .wrap2, .wrap3 {
display:inline-table;
/* \*/display:block;/**/
}
.wrap1 {
float:left;
background:url(shadow.gif) right bottom no-repeat;
}
.wrap2 { background:url(corner_bl.gif) left bottom no-repeat; }
.wrap3 {
padding:0 4px 4px 0;
background:url(corner_tr.gif) right top no-repeat;
}

From Onion Skinned Drop Shadows by Brian Williams on ALA

Drop shadows
The CSS3 way

box-shadow: 10px 5px 15px rgba(0,0,0,.5)

Drop shadows
The CSS3 way

box-shadow: 10px 5px 15px black inset

Drop shadows
The CSS3 way

box-shadow: 20px 20px 15px -15px #f09

Drop shadows
The CSS3 way

Multiple shadows, for complex effects:

box-shadow: 0 2px 6px rgba(0,0,0, .5),
0 1px rgba(255,255,255, .3) inset,
0 10px rgba(255,255,255, .2) inset,
0 10px 20px rgba(255,255,255, .25) inset,
0 -15px 30px rgba(0,0,0, .3);
Example originally conceived by Jan Henrik Helmers
box-shadow
Browser support*
Firefox
With
-moz-
Google Chrome
With
-webkit-
Opera
Full
support
Apple Safari
With
-webkit-
Internet Explorer
Full
support

* Assumes latest beta

Text shadows
The old way
<h1><img src="heading.png" alt="Heading text" 
     width="300" height="50" /></h1>

or, the slightly better:

<h1>Heading text</h1>
h1 {
background: url(heading.png) no-repeat;
width: 300px;
height: 50px;
text-indent:-9999px;
}
Text shadows
The CSS3 way

text-shadow: 1px .1em .3em black

Text shadows
The CSS3 way

I'm glowing

Text shadows
The CSS3 way

I have a rudimentary outline

Text shadows
The CSS3 way

You drank too much

Text shadows
The CSS3 way

Burning hot

text-shadow
Browser support*
Firefox
Full
support
Google Chrome
Full
support
Opera
Full
support
Apple Safari
Full
support
Internet Explorer
No
support

* Assumes latest beta

Gradients
The old way
Gradients
The CSS3 way

background: linear-gradient( #f09 , black )

Gradients
The CSS3 way

linear-gradient( -45deg , #f09 , black )

Gradients
The CSS3 way

linear-gradient( white , #f09 , black )

Gradients
The CSS3 way

linear-gradient( white , #f09 20% , black )

Gradients
The CSS3 way

radial-gradient( #f09 , transparent )

CSS gradients
Browser support*
Firefox
With
-moz-
Google Chrome
Al­ter­na­tive impl.
Opera
No
support
Apple Safari
Al­ter­na­tive impl.
Internet Explorer
No
support

* Assumes latest beta

Rotation and skew
The old way
Rotation
The CSS3 way

transform: rotate( -30deg )

Some text
Rotation
Example use case

From http://media.24ways.org/2009/14/5/index.html

Screenshot of a polaroid-style photo gallery using CSS rotate() transform
Skew
The CSS3 way

transform: skew( 30deg , -10deg )

Some text
More about CSS 2D transforms

More than just rotate and skew:

More about CSS 2D transforms

transform: rotate(30deg) skewX(30deg)

Some text
CSS 2D transforms
Browser support*
Firefox
With
-moz-
Google Chrome
With
-webkit-
Opera
With
-o-
Apple Safari
With
-webkit-
Internet Explorer
No
support

* Assumes latest beta

Problem #2

Markup & CSS clutter

Why is it a problem?
Multiple backgrounds
The old way

Multiple containers, 1 for each background image

<div class="foo">
<div class="inner">
	<div class="inner2"></div>
</div>
</div>
.foo { background: url(first_image.png); }
.foo .inner { background: url(second_image.png); }
.foo .inner2 { background: url(third_image.png); }
Multiple backgrounds
The CSS3 way
Multiple backgrounds
Browser support*
Firefox
Full
support
Google Chrome
Full
support
Opera
Full
support
Apple Safari
Full
support
Internet Explorer
Full
support

* Assumes latest beta

Fancy borders
The old way

3 containers for fixed width or height, 4+ for fluid boxes

<div class="foo">
<div class="inner">
	<div class="inner2"></div>
</div>
</div>
.foo {
background: url(img/border_top.png) top no-repeat;
padding-top:10px;
}
.foo .inner {
background: url(img/border_bottom.png) bottom no-repeat;
padding-bottom:10px;
}
.foo .inner2 {
background: url(img/border_middle.png) repeat-y;
}
Fancy borders
The CSS3 way

border-image: url(border-image.png) 14 repeat

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

The border-image used above, sliced
border-image.png
border-image
Real life use case

From http://gopinkboots.com/

Border image use case
border-image
Browser support*
Firefox
With
-moz-
Google Chrome
With
-webkit-
Opera
Full
support
Apple Safari
With
-webkit-
Internet Explorer
No
support

* Assumes latest beta

Alternating styling
for every n items
The old way

Using server side code or JavaScript to end up with something like that:

<ul>
<li class="odd"></li>
<li></li>
<li class="odd div3"></li>
<li></li>
<li class="odd"></li>
<li class="div3"></li>
</ul>
Alternating styling
for every n items
The CSS3 way

:nth-child ( odd )

Alternating styling
for every n items
The CSS3 way

:nth-child ( 3n )

Alternating styling
for every n items
The CSS3 way

:nth-child ( 3n+2 )

Note: Actually even == 2n and odd == 2n+1

Alternating styling
for every n items
The CSS3 way
Alternating styling
for every n items
More
:nth-something selectors
Browser support*
Firefox
Full
support
Google Chrome
Full
support
Opera
Full
support
Apple Safari
Full
support
Internet Explorer
Full
support

* Assumes latest beta

Selector negation
The old way

Writing 2 CSS rules for every negation we wanted

.post {
font-size:75%;
}

.post:first-child {
font-size: inherit;
}
Selector negation
The CSS3 way

.post :not ( :first-child ) { font-size: 75%; }

:not() pseudo-class
Browser support*
Firefox
Full
support
Google Chrome
Full
support
Opera
Full
support
Apple Safari
Full
support
Internet Explorer
Full
support

* Assumes latest beta

Image replacement
The old way
.icon {
background: url('some-icon.png');
width: 32px;
height: 32px;
text-indent: -9999px;
}
Image replacement
The CSS3 way
.icon {
content: url('some-icon.png');
}
content on every element
Browser support*
Firefox
No
support
Google Chrome
No
support
Opera
Full
support
Apple Safari
No
support
Internet Explorer
No
support

* Assumes latest beta

Problem #3

Needing present­ational JavaScript

Why is it a problem?
Transitions
The old way
Transitions
The CSS3 way

transition: 1.5s opacity ease-out

mouseover this
Transitions
The CSS3 way

transition: 2s opacity , .5s height ease-in

mouseover this
Transitions
The CSS3 way

transition: .5s height , .5s .5s width

Also available as a separate property (transition-delay)

CSS Transitions
Downsides
CSS transitions
Browser support*
Firefox
With
-moz-
Google Chrome
With
-webkit-
Opera
With
-o-
Apple Safari
With
-webkit-
Internet Explorer
No
support

* Assumes latest beta

Style changes according to the URL #hash
The old way

Check every few ms if the hash changed (no hashchange event in those days) and do stuff, like:

var oldHash = location.hash;
setInterval(function(){
if(location.hash != oldHash) {
    oldHash = location.hash;
    var targetHeading = document.getElementById(location.hash.substr(1));
    if(targetHeading) {
        targetHeading.className = 'target';
    }
}
}, 500);
Style changes according to the URL #hash
The CSS3 way
Style changes according to the URL #hash
The CSS3 way

This very slide is visible due to :target:

.slide {
z-index:1; opacity:0;
}

.slide:target {
z-index:100; opacity:1;
}
:target
Browser support*
Firefox
Full
support
Google Chrome
Full
support
Opera
Full
support
Apple Safari
Full
support
Internet Explorer
Full
support

* Assumes latest beta

Style reacting
to checkbox state
The old way
checkbox.addEventListener('change', function(){
var classes = this.nextElementSibling.classList;
if(this.checked) {
    classes.add('checkboxChecked');
} else {
    classes.remove('checkboxChecked');
}
});

Even worse in actual situations, where older browsers matter

Style reacting to
checkbox state
The CSS3 way

:checked
Real-world use case

Custom radios & checkboxes by Ryan Seddon

:checked
Browser support*
Firefox
Full
support
Google Chrome
Full
support
Opera
Full
support
Apple Safari
Full
support
Internet Explorer
Full
support

* Assumes latest beta

CSS values that depend on HTML attributes
The old way
CSS values that depend on HTML attributes
The CSS3 way

width: attr ( data-percent , % , 0 )

attr() in all properties
Browser support*
Firefox
No
support
Google Chrome
No
support
Opera
No
support
Apple Safari
No
support
Internet Explorer
No
support

* Assumes latest beta

Calculations
with different units
The old way

Setting the CSS property through JavaScript, performing the calculations on the computed styles, like:

var element = $(…);
element.css('width', .5 * $(element).parent().css('width') 
- element.css('borderLeftWidth') 
- element.css('borderRightWidth') 
- element.css('paddingLeft')
- element.css('paddingRight')
);

or just giving up altogether and using a very rough estimate (e.g. 48%)

Calculations
with different units
The CSS3 way
padding: .5em;
border: 1px solid;
width: calc(50% - 2*.5em - 2*1px);
calc()
Browser support*
Firefox
With
-moz-
Google Chrome
No
support
Opera
No
support
Apple Safari
No
support
Internet Explorer
Full
support

* Assumes latest beta

Sizing elements relative to viewport dimensions
The old way
var innerWidth = window.innerWidth 
|| (document.documentElement?
      document.documentElement.clientWidth 
      : 0
    ) 
|| document.body.clientWidth;

element.style.width = .5 * innerWidth + 'px';
Sizing elements relative to viewport dimensions
The CSS3 way

width: .5 vw

vw, vh, vm units
Browser support*
Firefox
No
support
Google Chrome
No
support
Opera
No
support
Apple Safari
No
support
Internet Explorer
Full
support

* Assumes latest beta

rem unit
Browser support*
Firefox
Full
support
Google Chrome
Full
support
Opera
No
support
Apple Safari
Full
support
Internet Explorer
Full
support

* Assumes latest beta

Appendix

Dealing with all these browsers

Why bother?
Graceful degradation
in a nutshell

Browsers ignore stuff they don’t understand

That includes:

If a CSS property is defined twice in the same rule, only the last one counts

Graceful degradation
in CSS values
background: black;
background: rgba(0, 0, 0, .75);
Dealing with
-vendor-prefixes

Just include all of them, browsers will pick the one they understand

-moz-transition: 1s ease-in;
-webkit-transition: 1s ease-in;
-o-transition: 1s ease-in;
transition: 1s ease-in;

Put the prefix-less version last

Detecting CSS
property support
in JavaScript
function isPropertySupported(property) {
if(property in document.body.style) return true;
    
var prefixes = ['Moz', 'Webkit', 'O', 'ms', 'Khtml'],
	prefProperty = property.charAt(0).toUpperCase() + property.substr(1);
	
for(var i=0; i<prefixes.length; i++) {
	if((prefixes[i] + prefProperty) in document.body.style) return true;
}

return false;
}
Detecting CSS
value support
in JavaScript
function isRGBASupported() {
var element = document.createElement('div');
    
try { element.style.color = 'rgba(0,0,0,.5)'; }
catch(e) { return false; }

return !!element.style.color;
}
Detecting CSS3
selector support
in JavaScript
function isSelectorSupported(selector) {
try {
   document.querySelector(selector);
   return true;
} catch(e) { return false; }
}
Detecting multiple features at once
a.k.a. Modernizr
http://www.modernizr.com
Screenshot of Modernizr's website
Last but not least...
Thank you!

Credits: