animation-iteration-delay hack

While there is no such property as an `animation-iteration-delay`, you can employ the `animation-delay` property, incorporate delays within your keyframe declaration, or use JavaScript to fake it. The best method for ‘faking it’ depends on the number of iterations, performance, and whether the delays are all equal in length.

What is an animation iteration delay? Sometimes you want an animation to occur multiple times, but want to wait a specific amount of time between each iteration.

Let’s say you want your element to grow 3 times, but want to wait 4 seconds between each 1s iteration. You can include the delay within your keyframe definition, and iterate through it 3 times:

.animate3times {
    background-color: red;
    animation: yellow;
    animation-iteration-count: 3;
    animation-duration: 5s;
 }
@keyframes yellow {
 80% {
    transform: scale(1);
    background-color:red;
  }
  80.1% {
    background-color: green; 
    transform: scale(0.5);
  }
  100% {
    background-color: yellow;
    transform: scale(1.5);
  }
 }

Note the first keyframe selector is at the 80% mark, and matches the default state. This will animate your element 3 times, staying in the default state for 80% of the 5 second animation, or for 4 seconds, and moving from green to yellow and small to big over the last 1 second of the animation duration, before iterating again, stopping after 3 iterations.

This method works for infinite repetitions of the animation as well. Unfortunately, it is only a good solution if the iteration delay between each iteration is identical. If you want to change the delay between each iteration, while not changing the duration of the change in size and color, you have to write a new @keyframes definition.

To enable different iteration delays between animations, we could create a single animation and bake in the effect of three different delays:

.animate3times {
    background-color: red;
    animation: yellow;
    animation-iteration-count: 1;
    animation-duration: 15s;
 }
@keyframes yellow {
  0%, 13.32%, 20.01%, 40%, 46.67%, 93.32% {
    transform: scale(1);
    background-color:red;
  }
  13.33%, 40.01%, 93.33% {
    background-color: green; 
    transform: scale(0.5);
  }
  20%, 46.66%, 100% {
    background-color: yellow;
    transform: scale(1.5);
  }
 }

This method may be more difficult to code and maintain. It works for a single cycle of the animation. To change the number of animations or the iteration delay durations, another keyframe declaration would be required.

The animation-iteration-delay hack

There’s a solution that currently works that is not specifically allowed in the animation specification, but it isn’t disallowed, and it’s supported: you can declare an animation multiple times, each with a different animation-delay.

.animate3times {
    animation: yellow, yellow, yellow;
    animation-delay: 0, 4s, 10s;
    animation-duration: 1s;
 }
@keyframes yellow {
  0% {
    background-color: green; 
    transform: scale(0.5);
  }
  100% {
    background-color: yellow;
    transform: scale(1.5);
  }
 }

See http://codepen.io/estelle/pen/PqRwGj.

We’ve attached the animation three times, each with a different delay. In this case, each animation iteration concludes before the next one proceeds. If they overlap, while they’re concurrently animating, the values will be the values from the last declared animation.

See http://codepen.io/estelle/pen/gpemWW

Of course, you can also use JavaScript with animationstart, animationiteration and animationend eventlisteners that add or remove animation names or classes from your element.

px to rem conversion if :root font-size is 16px

If you have

:root {
font-size: 16px;
}

you can use the following table to convert from PIXELS to REMS


10px 0.625rem
11px 0.6875rem
12px 0.75rem
13px 0.8125rem
14px 0.875rem
15px 0.9375rem
16px 1rem
17px 1.0625rem
18px 1.125rem
19px 1.1875rem
20px 1.25rem
21px 1.3125rem
22px 1.375rem
23px 1.4375rem
24px 1.5rem
25px 1.5625rem
26px 1.625rem
27px 1.6875rem
28px 1.75rem
29px 1.8125rem
30px 1.875rem
31px 1.9375rem
32px 2rem
33px 2.0625rem
34px 2.125rem
35px 2.1875rem
36px 2.25rem
37px 2.3125rem
38px 2.375rem
39px 2.4375rem
40px 2.5rem
41px 2.5625rem
42px 2.625rem
43px 2.6875rem
44px 2.75rem
45px 2.8125rem
46px 2.875rem
47px 2.9375rem
48px 3rem
49px 3.0625rem
50px 3.125rem
51px 3.1875rem
52px 3.25rem
53px 3.3125rem
54px 3.375rem
55px 3.4375rem
56px 3.5rem
57px 3.5625rem
58px 3.625rem
59px 3.6875rem
60px 3.75rem
61px 3.8125rem
62px 3.875rem
63px 3.9375rem
64px 4rem

Responsive Images: Clown Car Technique

Adaptive images are the current hot topic in the Adaptive Design and Responsive Web Design conversations. Why? Because no one likes any of the solutions. New elements and attributes are being discussed as a solution for what is, for most of use, a big headache.

We have foreground and background images. We have large displays and small displays. We have regular resolution and high resolution displays. We have good bandwidth and low bandwidth connections.

Some choose to “waste bandwidth” (and memory) by sending high-resolution images to all devices. Others send regular resolution images to all devices which look less crisp on high resolution displays.

When it comes to background images, we have media queries. This makes it (almost) simple to send the right size and resolution images based on the device pixel ratio, size and / or orientation of the screen.

Proposed solutions with new technology

With content images, it’s a bit more difficult. Most believe that there is no mechanism for the <img> tag to download the right size and resolution image. Polyfills have been created. Services have been formed.

The <picture> element leveraging the semantics of the HTML5 <video> elements, with its support of media queries to swap in different source files was proposed:

<picture alt="responsive image">
     <source src=large.jpg media="(min-width:1600px), (min-resolution: 136dpi) and (min-width:800px) ">
     <source src=medium.jpg media="(min-width:800px), (min-resolution: 136dpi) and (min-width:400px) ">
     <source src=small.jpg>
        <!-- fallback -->
        <img src=small.jpg alt="responsive image">
  </picture>

Another method, using a srcset attribute on the <img> element has also been proposed. The above would be written as:

 <img alt="responsive image"
           src="small.jpg"
           srcset="large.jpg 1600w, large.jpg 800w 1.95x, medium.jpg 800w, medium.jpg 400w 1.95x">

Possible Solutions with Existing Tech: SVG

What many people don’t realize is we already have the technology to serve responsive images. We have had browser support for responsive images for a long, long time! SVG has supported media queries for a long time, and browsers have supported SVG for … well, not quite a long time, but still. Most browsers support media queries in the SVG (test your browser). The main issue is terms of mobile is old Androids lack of support until 3.0..

We can use media queries within SVG to serve up the right image. The beauty of the "Clown Car" technique is that all the logic remains in the SVG file. I’ve called it the "Clown Car" technique since we are including (or stuffing) many images (clows) into a single image file (car).

When you mark up your HTML, you simply add a single call to an SVG file.

<img src="awesomefile.svg" alt="responsive image">

Now isn’t that code simple?

The magic is that SVG supports both media queries and rasterized images.

In our SVG file, using the <image> element, will include the all the images that we may need to serve, and include all the media queries.

Here is the code for one of the SVG files:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="329">
  <title>The Clown Car Technique</title>
    <defs>
    <style>
    image {display: none;}
    #small {display: block}
     @media screen and (min-width: 401px) and (max-width: 700px) {
        #medium {display: block}
        #small {display: none}
    }
      @media screen and (min-width: 701px) and (max-width: 1000px) {
        #big {display: block}
        #small {display: none}
    }
     @media screen and (min-width: 1001px)  {
      #huge {display: block}
      #small {display: none;}
    }
    </style>
  </defs>
  <g>
    <image id="small"  height="329" width="300" xlink:href="images/small.png" />
    <image id="medium" height="329" width="300" xlink:href="images/medium.png" />
    <image id="big"    height="329" width="300" xlink:href="images/big.png" />
    <image id="huge"   height="329" width="300" xlink:href="images/huge.png" />
  </g>
  </svg>

Unfortunately, when this file is used, all 4 PNGs are retrieved from the server. To solve this issue, we can use background images instead:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 329" preserveAspectRatio="xMidYMid meet">
 <title>Clown Car Technique</title>
 <style> 
  svg {
    background-size: 100% 100%;
    background-repeat: no-repeat;
  } 
 @media screen and (max-width: 400px) {
  svg {background-image: url(images/small.png");}
 } 
 @media screen and (min-width: 401px) and (max-width: 700px) {
  svg {background-image: url(images/medium.png);}
 } 
 @media screen and (min-width: 701px) and (max-width: 1000px) {
  svg {background-image: url(images/big.png);}
 } 
 @media screen and (min-width: 1001px) {
  svg {background-image: url(images/huge.png);}
 }
 </style>
</svg>

This version only downloads the images required, thereby solving the multi-HTTP and waste of bandwidth concerns. However, it seems to trigger mor Content Security Policy issues than the previous SVG.

The SVG file has it’s own declared size, but when included in HTML, the media query size is based on the proportions of the DOM node in the HTML –. it reflect thespace provided to it.

Open the first SVG file or the second SVG file in your browser, then grow and shrink your browser window. As the window grows and shrinks the image the SVG displays changes. The image size appears to stay the same — because it is the same. In the SVG, all the images to have the same dimensions. Its when we include the SVG in a flexible layout that the magic happens. You’ll note that the first time you load the second one there may be flickers of white as the browser requests the next required PNG.

When you include the SVG in your HTML <img> with a flexible width, such as 70% of viewport, as you grow and shrink the container, the image responds to the changes. The "width" media query in the SVG is based on the element width in which the SVG is contained, not the viewport width.

I have included the first SVG and the second SVG so you can see SVG with both foreground and background images. These foreground images work perfectly in Opera. In Chrome and Safari, I need to open the SVG file first, after which the HTML file containing the foreground SVG image works perfectly*. In Firefox, the SVG works. Firefox supports SVG and supports SVG as background image, but blocks the importing of external raster images due to their content security policy (CSP).

The content security policy does make sense: you don’t want a file to be pulling in untrustworthy content. SVG technology is supported. It is just being prevented from pulling in external raster image. Firefox prevents it altogether. Safari and Chrome work if the SVG is preloaded. We can work with the browser vendors to get this CSP lifted.

The browsers do all support the media queries with the SVG. They all support SVG as foreground or content images. They all support SVG as background images. The support just isn’t all the same.

Responsive SVG for foreground images works. It simply works right out of the box. For background images, it works, but I am still tweaking the code to make the background responsive (in Chrome it works if background-size is declared, but Opera and Safari are using the declared SVG size as the image size… still working on combinations that work everywhere.)

The drawback of the first SVG is that the SVG file is making 4 http requests. So, while we are displaying the right image, we are not saving bandwidth. In the second, the raster images are background image. Only the required image is downloaded.

Another pro for this technique: similar to how we separate content from presentation from behavior: this method enables us to also separate out images — all the logic is in the SVG image instead of polluting our CSS or HTML.

With <object> tag: up Next

<object> can take care of Content Security Policy drawback we see with <img> that disallows the importing of images or script into an <img> file. <object> allows both. I am working on that angle now.

The main question is: should we attempt this with <object>, or should we get browser vendors to change their content security policy?

Note:

* Interestingly, the SVG works best when the raster images are pulled cross domain rather than same origin. You would think, with CSP, it would be the exact opposite.

Web Development Tips

My Twitter account, WebDevTips, has been reactivated. Follow @webDevTips to get (almost) daily Web Development tips in your timeline.


details and summary polyfill

var summaryClick = function(elem){
  if (!('open' in document.createElement('details'))){
    var deetails = elem.parentNode;
    if(deetails.hasAttribute('open')){
     deetails.removeAttribute('open');
    } else {
     deetails.setAttribute('open', 'open')
    }
  }
}

add the summaryClick to your <summary> click event listeners

And then in my CSS I put something similar to:

details:not([open]) {
   height: 2em; 
   overflow: hidden;
}
details[open]  {
   height: auto;
}
summary::before {
   content: "▶ ";
}

Only browsers that understand the JS used will understand the selectors used. So, this isn’t fool proof, but it’s nice, quick and dirty.

SpeciFISHity: CSS Specificity

Some people are confused by CSS Specificity, especially with all of the (not-so) new CSS3 Selectors. The image below may help make sense of CSS Specificity.

X-0-0: The number of ID selectors, represented by Sharks
0-Y-0: The number of class selectors, attributes selectors, and pseudo-classes, represented by Fish
0-0-Z: The number of type selectors and pseudo-elements, represented by Plankton a la Spongebob
*: The universal selector has no value

Download the specificity chart and read the rest of the SpeciFISHity article here

HSLA Color Picker / RGBA Converter

color:hsla(
328,   H  
blah

100%,   S  

44%,   L  

1.00   A  

);

HSLA Colors

Introducing border-radius

Designers have been including rounded corners in their designs for years. In the early 2000s, when webmasters were creating table based layout, they would include tiny little table cells to add in little corners. With the end of table based layouts, web masters created nifty little tricks. From sliding doors to adding corners with javascript, to the three slice technique, we tried and cried over it all since 2004. Our solutions have involved hours of slicing and dicing images, and millions of non-semantic html hooks for those image.

A little history

Requiring images for decorative corners is a maintenance nightmare. The extra http requests to serve the images slowed down the page load and added to site bandwidth. Rounded corners require either 4 separate images — one for each corner — or a larger sprite image that includes all 4 corners if the design allows, which requires the addition of three, and sometimes 4, hooks for those corners.
And for what? A little decoration.

No more! Enough with markup clutter, extra http requests for decorative images
and JavaScript for presentation. It’s time to let the browser do our heavy lifting, especially since this ‘heavy lifting’ is really very light weight.

The CSS3 border-radius property is not supported on over 60% of the browsers surfing the web. So, why aren’t you using them? The CSS3 border-radius property allows you to create native rounded corners using only CSS. No divitis. No classitis. No extra http requests. No wasted hours in Photoshop.

The border radius property first raised it’s beautiful little head in 2005. Webkit was the first to support the border-radius property, but seemingly is the last to fully support it (more about that later).

With the border-radius property, you can create rounded corners without images in all modern browsers and IE9. You can create rounded corners, elliptical corners, uneven corners and odd effects.

So, how do you create these rounded corners? The syntax is slightly different for rounded corners than for elliptical corners. You can created 4 identical rounded corners with a single value, declare up to four different values — one for each rounded corner, or declare uneven corners by separating the horizontal radius from the vertical radius declarations with a slash in the shorthand or space in the long hand.

Most designs call for rounded corners, so let’s start with round corners first:

The syntax (round corners):

You can use the shorthand to declare identical (declare one value) or up to four different sized corner radii. Or, you can use the long hand to declare each corner separately:

border-radius:  <all-four-same-sized-corners>;
border-radius:  <TL & BR> <TR & BL>;
border-radius:  <TL> <TR> <BR> <BL>;

or

border-top-right-radius: <TR>;
border-bottom-right-radius: <BR>;
border-bottom-left-radius: <BL>;
border-top-left-radius: <TL>;

The code:

Generally, you will want all four corners to have the same look and feel, so you will want all four corners to be equal EXCEPT in the case of top navigation bar tabs, where you will want the top corners to be round and the bottom corners to be rectangular.

You can use the shorthand:

.box {
    border-radius: 1em;
    }
.tab {
    border-radius: 0.5em 0.5em 0 0;
}

or you can use the longhand:

.box {
    border-top-right-radius: 1em;
    border-bottom-right-radius: 1em;
    border-bottom-left-radius: 1em;
    border-top-left-radius: 1em;
    }
.tab {
    border-top-right-radius: 0.5em;
    border-bottom-right-radius: 0.5em;
}

The above will create rounded corners: the vertical and horizontal sides of each corner will be the same: the horizontal radius is the same as the vertical radius. But what if you want elliptical corners? Rounded, but not actually round? Border radius allows for that.

The syntax (rounded or elliptical corners):

If you want rounded corners that are elliptical instead of round, there’s a syntax for that. In the shorthand syntax, separate the horizontal radius from the vertical radius declarations with a slash.

border-radius:  <vertical-radius values> / <horizontal-radius values>;
border-radius:  <TL & BR> <TR & BL> / <TL & BR> <TR & BL>;
border-radius:  <TL> <TR> <BR> <BL> / <TL> <TR> <BR> <BL> ;

If you are using the longhand properties, separate the two radii with a space instead. Notice the values above have a slash, the values below do not.

border-top-right-radius: <TR vertical> <TR horizontal>;
border-bottom-right-radius: <BR vertical> <BR horizontal>;
border-bottom-left-radius: <BL vertical> <BL horizontal>;
border-top-left-radius: <TL vertical> <TL horizontal>;

The code:

These two declarations are equivalent

.shorthand {
    border-radius: 2em 1em 4em 3em/ 0.5em 3em;
    }
 
.longhand {	
    border-top-left-radius:     2em 0.5em;
    border-top-right-radius:    1em 3em;
    border-bottom-right-radius: 4em 0.5em;
    border-bottom-left-radius:  3em;
    }

And now for the bad news

While border-radius property has widespread browser support, there are some discrepancies in browser support.

Older Internet Explorer versions

Border-radius is not supported in IE6, IE7 or IE8. Remember that users access your web site with only one browser. They don’t look at all the different browsers: only web developers do that. So, visitors using these browsers will not see your beautifully rounded corners, but they also won’t know that they are missing anything. Rounded corners are an enhancement. They’re generally not critical to the content of your site. There’s an HTC file called CSS Curved Corner by Remiz Rahnas that can create rounded corner effects for old versions of IE.

Older non-IE browsers that are still lingering

If you’re still supporting Firefox 3.6 and or Safari 4 you’ll want to add the -moz- and -webkit- vendor prefixes respectively. Since Safari 5 was released over a year ago, and Safari 4 has less than 0.75% market share, I have dropped the -webkit- prefix syntax. At the time of this writing, while Firefox 4 has surpassed Firefox 3.6 in the USA market, the trend is not worldwide, so I am still including -moz- prefixed corners. Also, older versions of Firefox used a non-standards syntax for the long hand, so when declaring -moz- prefixed border radii, use the shorthand. If you want to use the long hand, I recommend using the border radius generator to get the FF3.6 and Safari 4 and earlier long hand markup.

Quirks in Modern Browsers

Opera, IE9, Safari 5, Firefox 4 and Chrome all understand the vendorless recommended standard syntax for the four long hand properties and the single shorthand border-radius property, but some browsers do have some bugs:

Safari 5 does not understand percentage values for rounded corners. This is resolved in the webkit nightly builds, so will be resolved in Safari 6. In the meantime, since it doesn’t understand %, it will ignore the entire declaration. The hack is to declare the border radius in other length units first, then declare your percent version for all browsers that do understand percentage values.

Opera currently also have bugs with percentage values. It does understand percents, but does not render them correctly in some cases. The values in elliptical corners is slightly off, and has been fixed in the Opera Next build (build 1024), so will be fixed in their next launch most likely. In most cases, therefore, a hack may not be necessary. When an element is floated, the border radius is completely off in Opera. The border-radius is huge, making the element look almost rectangular, as if there were no border-radius set. If you’re ok with graceful degradation, the Opera user won’t be negatively impacted: they will just see almost what IE 7 users see. If you’re not OK with that, either don’t float your rounded elements if you’ve used percentage values as your radius length, or use other length types (em, px, etc) if your element is floated.