Rotating Words With CSS Animations – CSS3 Keyframes Animation Example

In today’s tutorial we’ll create another typography effect. The idea is to have some kind of sentence and to rotate a part of it. We’ll be “exchanging” certain words of that sentence using CSS animations.
Please note: the result of this tutorial will only work as intended in browsers that support CSS animations.
So let’s start!

In the following, we’ll be going through demo.

rotating-words-css-animations

THE HTML

We’ll have a main wrapper with a h2 heading that contains first-level spans and two divisions for the rotating words:

<section class="rw-wrapper">
	<h2 class="rw-sentence">
		<span>Real poetry is like</span>
		<br />
		<span>creating beautiful butterflies</span>
		<br />
		<span>with a silent touch of</span>
		<div class="rw-words rw-words-1">
			<span>spice</span>
			<span>colors</span>
			<span>happiness</span>
			<span>wonder</span>
			<span>sugar</span>
			<span>happiness</span>
		</div>
	</h2>
</section>

Now, ignoring the garbage placeholder text, we want each span of the rw-word to appear at a time. For that we’ll be using CSS animations. We’ll create one animation for each division and each span will run it, just with different delays.
So, let’s look at the CSS.

THE CSS3

First, we will style the main wrapper and center it on the page:

.rw-wrapper{
	width: 80%;
	position: relative;
	margin: 110px auto 0 auto;
	font-family: 'Bree Serif';
	padding: 10px;
	height: 400px;
	overflow: hidden;
}

We’ll add some text shadow to all the elements in the heading:

.rw-sentence{
	margin: 0;
	text-align: left;
	text-shadow: 1px 1px 1px rgba(255,255,255,0.8);
}

And add some specific text styling to the spans:

.rw-sentence span{
	color: #444;
	white-space: nowrap;
	font-size: 200%;
	font-weight: normal;
}

The divisions will be displayed as inline elements, that will allow us to “insert” them into the sentence without breaking the flow:

.rw-words{
	display: inline;
	text-indent: 10px;
}

Each span inside of a rw-words div will be positioned absolutely and we’ll hide any overflow:

.rw-words span{
	position: absolute;
	opacity: 0;
	overflow: hidden;
	color: #888;
	-webkit-transform-origin: 10% 75%;
	-moz-transform-origin: 10% 75%;
	-ms-transform-origin: 10% 75%;
	-o-transform-origin: 10% 75%;
	transform-origin: 10% 75%;
}

Now, we’ll run two animations. As mentioned previously, we’ll run the same animation for all the spans in one div, just with different delays:

.rw-words-1 span{
	animation: rotateWord 16s linear infinite 0s;
}
.rw-words-2 span{
    animation: rotateWordsSecond 18s linear infinite 0s;
}
.rw-words span:nth-child(2) {
	animation-delay: 3s; 
	color: #6b889d;
}
.rw-words span:nth-child(3) {
	animation-delay: 6s; 
	color: #6b739d;	
}
.rw-words span:nth-child(4) {
	animation-delay: 9s; 
	color: #7a6b9d;
}
.rw-words span:nth-child(5) {
	animation-delay: 12s; 
	color: #8d6b9d;
}
.rw-words span:nth-child(6) {
	animation-delay: 15s; 
	color: #9b6b9d;
}

Our animations will run one cycle, meaning that each span will be shown once for three seconds, hence the delay value. The whole animation will run 6 (number of images) * 3 (appearance time) = 18 seconds.
We will need to set the right percentage for the opacity value (or whatever makes the span appear). Dividing 6 by 18 gives us 0.333… which would be 33% for our keyframe step. Everything that we want to happen to the span needs to happen before that. So, after tweaking and seeing what fits best, we come up with the following animation (Fade in and “fall”) for the first words:

@keyframes rotateWord {
    0% { opacity: 0; }
    5% { opacity: 1; }
    17% { opacity: 1; transform: rotate(0deg); }
	19% { opacity: 1; transform: rotate(98deg); }
	21% { opacity: 1; transform: rotate(86deg); }
	23% { opacity: 1; transform: translateY(85px) rotate(83deg); }
	25% { opacity: 0; transform: translateY(170px) rotate(80deg); }
	80% { opacity: 0; }
    100% { opacity: 0; }
}

We’ll fade in the span and we’ll also animate its height.
The animation for the words in the second div will fade in and animate their width. We added a bit to the keyframe step percentages here, because we want these words to appear just a tiny bit later than the ones of the first word:

@keyframes rotateWordsSecond {
    0% { opacity: 1; animation-timing-function: ease-in; width: 0px; }
    10% { opacity: 0.3; width: 0px; }
    20% { opacity: 1; width: 100%; }
    27% { opacity: 0; width: 100%; }
    100% { opacity: 0; }
}

css3-animations-rotating-words

And that’s it folks! There are many possibilities for the animations, you can check out the demo and see what can be applied!
I hope you enjoyed this tutorial and find it inspiring!
view demo

 

Posted by: Dhiraj kumar

Unquoted font family names in CSS

CSS

Are the quotes in font-family: 'Comic Sans MS' required, or not?

According to the the CSS validator, the quotes are supposed to be there in this case because the font family name contains spaces:

Family names containing whitespace should be quoted. If quoting is omitted, any whitespace characters before and after the name are ignored and any sequence of whitespace characters inside the name is converted to a single space.

However, this is an error in the CSS validator. The warning message suggests that all font family names containing whitespace should be quoted, which is simply not true. font-family: Comic Sans MS (without quotes) is perfectly valid CSS that works the way you’d expect it to.

In reality, it’s a bit more complex. To grok the rules on font family names, we need to understand the difference between CSS strings and identifiers first.

Strings and identifiers

The spec says the following about strings:

Strings can either be written with double quotes or with single quotes.

Identifiers are defined as follows:

In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters[a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_).

ISO 10646 defines the Universal Character Set, which correlates to the Unicode standard. Note that they’re actually talking about the hyphen-minus character — not the hyphen character, which is U+2010. The code point for hyphen-minus is U+002D, and for underscore (low line) it’s U+005F. The highest code point currently allowed by Unicode is U+10FFFF. So, any character matching the regular expression [-_\u00A0-\u10FFFF] is allowed in an identifier.

The spec continues:

[Identifiers] cannot start with a digit, two hyphens, or a hyphen followed by a digit. Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code […]. For instance, the identifier B&W? may be written as B\&W\? or B\26 W\3F .

Translated into regex: any string that matches ^(-?\d|--) is not a valid CSS identifier.

Whitespace

Both the CSS 2.1 and CSS3 Fonts Module Level 3 specs say:

Font family names must either be given quoted as strings, or unquoted as a sequence of one or more identifiers. This means most punctuation characters and digits at the start of each token must be escaped in unquoted font family names.

Note: “a sequence of one or more identifiers” implies that multiple space-separated identifiers will form a single font family name. Therefore, font-family: Comic Sans MS is valid, and equivalent to font-family: 'Comic Sans MS'. The former consists of three space-separated identifiers, the latter is simply a string.

This is clarified a few paragraphs down in the spec:

If a sequence of identifiers is given as a font family name, the computed value is the name converted to a string by joining all the identifiers in the sequence by single spaces.

The aforementioned CSS validator warning describes what happens if leading or trailing whitespace is used around identifier sequences:

[A]ny whitespace characters before and after the name are ignored, and any sequence of whitespace characters inside the name is converted to a single space.

This is implied by the spec text, too: an unescaped whitespace character can never be part of an identifier, so it can never start a “sequence of identifiers”.

Generic family keywords

The spec defines the following generic family keywords: serifsans-serifcursivefantasy, andmonospace. These keywords can be used as a general fallback mechanism, in case the desired font choices are not available. Authors are encouraged to append a generic font family as a last alternative for improved robustness. As keywords, they must not be quoted.

In other words, font-family: sans-serif means that a generic sans-serif font family will be used, whilefont-family: 'sans-serif' (with quotes) refers to an actual font that goes by the name of sans-serif. A very important difference!

Other keyword values

The same behavior applies to a few other keywords, too:

Font family names that happen to be the same as a keyword value (inheritserifsans-serifmonospace,fantasy, and cursive) must be quoted to prevent confusion with the keywords with the same names. The keywords initial and default are reserved for future use and must also be quoted when used as font names. User agents must not consider these keywords as matching the <family-name> type.

Note that all keywords are case-insensitive. For example, Monospacemonospace, and mOnOsPaCe all refer to the same keyword, and if you want to use a font with that exact family name rather than the default keyword value, you’ll need to quote it.

Summary

As long as the only disallowed characters in an otherwise valid identifier are single U+0020 space characters, and all space-separated parts are valid identifiers too, the identifier sequence can be used as an unquoted font family name (unless it’s a keyword, but there are no keywords with spaces in them).

If a font family name matches a keyword, it must be quoted to form a string.

If you want to use an invalid CSS identifier as (part of) a font family name, you’ll need to quote it to form a string instead; or you could just escape any special characters so it can remain an unquoted identifier.

Here are some example font-family declarations:

/* Invalid because `/` is not allowed in an identifier: */ font-family: Red/Black;
 /* Valid — an escaped `/` symbol is allowed in an identifier: */ font-family: Red\/Black;
 /* Invalid because a string cannot be combined with an identifier: */ font-family: 'Lucida' Grande;
 /* Valid — it’s a single string: */ font-family: 'Lucida Grande';
 /* Valid — it’s a space-separated sequence of two identifiers: */ font-family: Lucida Grande;
 /* Valid — it’s still a space-separated sequence of two identifiers: */ font-family: Lucida     Grande;
 /* Invalid because `!` is not allowed in an identifier: */ font-family: Ahem!;
 /* Valid — it’s a string: */ font-family: 'Ahem!';
 /* Valid — an escaped `!` is allowed in an identifier: */ font-family: Ahem\!;
 /* Invalid because an identifier cannot start with a digit: */ font-family: Hawaii 5-0;
 /* Valid — it’s a string: */ font-family: 'Hawaii 5-0';
 /* Valid — `\35 ` (including the space) is an escape sequence for `5`: */ font-family: Hawaii \35 -0;
 /* Valid — `\ ` (including the space) is an escape sequence for ` `: */ font-family: Hawaii\ 5-0;
 /* Invalid — `$` is not allowed in an identifier: */ font-family: $42;
 /* Valid — an escaped `$` symbol is allowed in an identifier: */ font-family: \$42;
 /* Valid — `€` is allowed in an identifier: */ font-family: €42;

Bonus puzzle: Other than keywords, I can only think of one font family name that can’t be used without quotes — there is no way to escape it in an identifier. Do you know which one?

Posted by: Dhiraj kumar

HTML5 Logo Design Using CSS3

css3-html5-logoAs you probably found out, some time ago, the The World-Wide Web Consortium (W3C) has unveiled the HTML5 Logo. They launched more than a logo as they got also a full branding, including badges, t-shirts and stickers.

So, I suppose that’s a good thing, that HTML5 got some branding, sounds very interesting!

While looking at it and admiring it, as I find it very nice, I thought about how can I do it with CSS3 (typically for me).

What about the logo? It’s A Bird… It’s A Plane…

No, it’s the new HTML5 logo and in this article I’ll design it using only CSS!

HTML5-logo

Concept

Getting back to our work, I thought about the ingredients I’d need for this angular orange shield:

CSS borders shapes

I used borders in order to create the shield icon.

:before and :after pseudo-elements

Using this type of selectors it’s helpful when you want to achieve a minimal HTML markup.

CSS3 opacity and transform

Even if the article’s name says : “HTML5 Logo made with CSS3”, this isn’t mainly about CSS3, but, opacity and transform properties were very useful for this.

Custom font

The method I’ll use to display the 5 number is to include the Geo font via Google Font API.

I know it’s not identical, but, at the time I wrote this article, I found it quite similar. Instead, I’d appreciate if you could suggest me a better font to use for the number.

For a perfect result, I guess I could have used CSS3 skew transformation and a lot of empty divs to create the “5” number …

HTML5

<div id="wrapper">
    <span>5</span>

    <div class="inner"></div>
    <div class="inner left"></div>
    <div class="inner left cover"></div>    
</div>

CSS3

#wrapper {
        position: relative;
        width: 340px;
        margin: 10px auto 30px auto;
    }

    #wrapper span {
        font: normal 475px/305px 'Geo', serif;
        width: 340px;
        text-align: center;
        position: absolute;
        top: 0;
        z-index: 9999;
        color: white;
    }    

    #wrapper:before {
        content: '';
        display: block;
        /*340 total width */
        border-left: 30px solid transparent;
        border-right: 30px solid transparent;
        border-top: 345px solid #e34c26;
        width: 280px;
    }

    #wrapper:after {
        content: '';
        display: block;
        /*280 total width */        
        border-left: 140px solid transparent;
        border-right: 140px solid transparent;
        border-top: 40px solid #e34c26;
        width: 0;
        margin-left: 30px;
    }

    /**/

    .inner {
    position: absolute;
    top: 0;

    -moz-transform: scale(0.85);
    -webkit-transform: scale(0.85);
    -o-transform: scale(0.85);
    -ms-transform: scale(0.85);
    transform: scale(0.85);	
    }

    .inner:before {
        content: '';
        display: block;
        /*340 total width */
        border-left: 30px solid transparent;
        border-right: 30px solid transparent;
        border-top: 345px solid #f06529;
        width: 280px;
    }

    .inner:after {
        content: '';
        display: block;
        /*280 total width */        
        border-left: 140px solid transparent;
        border-right: 140px solid transparent;
        border-top: 40px solid #f06529;
        width: 0;
        margin-left: 30px;

        position: relative;
        top: -1px; /* Fix spacing */
    }

    /**/

    .inner.left {
        width: 170px; /* half from the 340px total width */
        overflow: hidden;
        -moz-transform: scale(1);
        -webkit-transform: scale(1);
        -o-transform: scale(1);
        -ms-transform: scale(1);		
        transform: scale(1);		
    }

    .inner.left:before {
        border-top-color: #e34c26;
    }

    .inner.left:after {
        border-top-color: #e34c26;
    }

    /**/

    .inner.left.cover {
        z-index: 10000;
        opacity: 0.1;
    }

Custom Font From Google Font API

<link href='http://fonts.googleapis.com/css?family=Geo' rel='stylesheet' type='text/css'>

My initial result:

HTML5-logo

I know it’s not perfect, especially the 5 number, but I hope you will still like it!

Updated result

I finally made it, I updated the initial HTML5 logo. Instead the custom font, empty divs were used in order to replicate the logo.

Now you have it! Minimal HTML markup, CSS3 transforms and pseudo-elements:-

HTML5

<div id="wrapper">        
    <div id="five">
        <div class="top"></div>
        <div class="left-top"></div>
        <div class="middle"></div>
        <div class="right"></div>
        <div class="bottom"></div>
        <div class="left-bottom"></div>      
    </div>

    <div class="inner"></div>
    <div class="inner left"></div>

    <div class="inner left cover"></div>    
</div>

CSS

h1 {
        font: bold 90px 'arial black';
        margin: 20px 0 0 0;
        text-align: center;
    }

    p {
        text-align: center;
    }

    /**/

    #wrapper {
        position: relative;
        width: 340px;
        margin: 10px auto 30px auto;
    }

    /**/

    #five {
        position: absolute; 
        z-index: 1;
        top: 0;
    }

    #five div,  #five div:after {
        position: absolute;
        background: #fff;
    }    

    #five .left-top {
        width: 40px;
        height: 130px;
        top: 72px;
        left: 70px;
        -webkit-transform: skew(5deg);
        -moz-transform: skew(5deg);
        -o-transform: skew(5deg);
		-ms-transform: skew(5deg);
		transform: skew(5deg);		
    }

    #five .top {
        width: 90px;
        height: 40px;        
        top: 72px;
        left: 80px;
    }

    #five .top:after {
        content: '';        
        left: 85px;
        top: 0;
        height: 40px;        
        width: 110px;
        -moz-transform: skew(-5deg);
        -webkit-transform: skew(-5deg);
        -o-transform: skew(-5deg);
		-ms-transform: skew(-5deg);		
		transform: skew(-5deg);
    }

    #five .middle {
        width: 96px;
        height: 40px;
        top: 162px;
        left: 75px;
    }

    #five .middle:after {    
        content: '';        
        top: 0;
        left: 96px;
        width: 80px;
        height: 40px;        
    }

    #five .right {
        left: 225px;
        top: 162px;
        height: 125px;        
        width: 40px;
        -moz-transform: skew(-5deg);
        -webkit-transform: skew(-5deg);
        -o-transform: skew(-5deg);
		-ms-transform: skew(-5deg);	
		transform: skew(-5deg);			
    }

    #five .bottom {	
        width: 90px;
        height: 40px;
        top: 260px;
        left: 87px;
        -webkit-transform: rotate(14deg);
        -moz-transform: rotate(14deg);
        -o-transform: rotate(14deg);  
		-ms-transform: rotate(14deg);		
		transform: rotate(14deg);		
    }

    #five .bottom:after {
        content: '';        
        left: 73px;
        top: -19px;
        height: 40px;        
        width: 94px;       
        -webkit-transform: rotate(-28deg);
        -moz-transform: rotate(-28deg);
        -o-transform: rotate(-28deg);
		-ms-transform: rotate(-28deg);	
		transform: rotate(-28deg);		
    }

    #five .left-bottom {	
        width: 40px;
        height: 65px;
        top: 222px;
        left: 80px;
        -webkit-transform: skew(5deg);
        -moz-transform: skew(5deg);
        -o-transform: skew(5deg);    
		-ms-transform: skew(5deg);	
		transform: skew(5deg);
    }

     /**/   

    #wrapper:before {
        content: '';
        display: block;
        /*340 total width */
        border-left: 30px solid transparent;
        border-right: 30px solid transparent;
        border-top: 345px solid #e34c26;
        width: 280px;
    }

    #wrapper:after {
        content: '';
        display: block;
        /*280 total width */        
        border-left: 140px solid transparent;
        border-right: 140px solid transparent;
        border-top: 40px solid #e34c26;
        width: 0;
        margin-left: 30px;
    }

    /**/

    .inner {
        position: absolute;
        top: 0;

        -moz-transform: scale(0.85);
        -webkit-transform: scale(0.85);
        -o-transform: scale(0.85);
		-ms-transform: scale(0.85);	
		transform: scale(0.85);		
    }

    .inner:before {
        content: '';
        display: block;
        /*340 total width */
        border-left: 30px solid transparent;
        border-right: 30px solid transparent;
        border-top: 345px solid #f06529;
        width: 280px;
    }

    .inner:after {
        content: '';
        display: block;
        /*280 total width */        
        border-left: 140px solid transparent;
        border-right: 140px solid transparent;
        border-top: 40px solid #f06529;
        width: 0;
        margin-left: 30px;

        position: relative;
        top: -1px; /* Fix spacing */
    }

    /**/

    .inner.left {
        width: 170px; /* half from the 340px total width */
        overflow: hidden;
        -moz-transform: scale(1);
        -webkit-transform: scale(1);
        -o-transform: scale(1);
		-ms-transform: scale(1);
		transform: scale(1);
    }

    .inner.left:before {
        border-top-color: #e34c26;
    }

    .inner.left:after {
        border-top-color: #e34c26;
    }

    /**/

    .inner.left.cover {
        z-index: 10000;
        opacity: 0.1;
    }

HTML5-logo

Browser support

Latest versions of:

  • Mozilla
  • Chrome
  • Safari
  • Opera
  • IE9

view demo

 

Posted by: Dhiraj kumar

Google Font API and Typekit solutions VS CCS3 @font-face

A quick tutorial here about setting up your website with custom fonts using @font-face.  I am also sharing these alternative solutions, pros and cons.

The aim of this post is to briefly round up your options when using custom fonts in web design.

google-and-typekit-versus-font-face

CSS3 @font-face

The @font-face was first proposed for CSS2 and has been implemented in Internet Explorer since version 5.  However, their implementation relied on the proprietary Embedded Open Type (.eot) format, and no other browsers decided to use this format until Safari 3.1 was released.

Since then, web designers began to use .ttf or .otf fonts for their websites and now this CSS property is well-known.

css3-font-face

CSS

@font-face {
        font-family: '3DumbRegular';
        src: url('3Dumb-webfont.eot');
        src: local('?'), url('3Dumb-webfont.woff') format('woff'), url('3Dumb-webfont.ttf') format('truetype'), url('3Dumb-webfont.svg#webfont57ztNrX6') format('svg');
}

h1 {
  font-family: '3DumbRegular', Arial, sans-serif
}

Pros

  • A lot of available fonts you can choose from. Check this detailed list.
  • It works for all browsers.
  • It has no JavaScript dependency.

Cons

  • It takes slightly longer to implement than Google Font API (more code).
  • Quality of font rendering may differ browser to browser.
  • Your CSS may not be validated, depending on your DOCTYPE.

Google Font API

To use the fonts of Google’s font library, just go to http://code.google.com/webfonts and select a font. If you choose “Cantarell” font for example, include the following code into your files.

google-font-api

HTML

<link href="http://fonts.googleapis.com/css?family=Cantarell&subset=latin" rel="stylesheet" type="text/css">

CSS

h1 {
  font-family: 'Cantarell', arial, serif; /*Add also some font replacements, just in case...*/
}

Pros

  • Free solution from Google.
  • Quick set up.
  • No JavaScript dependency.
  • No need to think about font licensing.

Cons

  • Small number of fonts to choose from. (just for now, I hope)
  • Quality of font rendering may differ browser to browser.
  • No support for iPhone or iPad. Support added from iOS 4.2+ (iPhone, iPad, iPod).

Typekit

Typekit is a service launched by Small Batch, Inc. which, via JavaScript and a subscription service, allows webmasters and designers to embed non-standard, non-system-specific fonts into online documents. It uses the @font-face CSS property and is available to the public as a paid service.

typekit

HTML

<head>
        <script type="text/javascript" src="http://use.typekit.com/typekitid.js"></script>
        <script type="text/javascript">try{Typekit.load();}catch(e){}</script>
</head>

CSS

h1 {
        font-family: "museo-sans-1", "museo-sans-2", sans-serif;
}

Pros

  • Huge fonts library.
  • Good support articles and help section.
  • iPad, iPhone/iPod Touch support (experimental)
  • Control the behavior of your page as web fonts load (thanks @smcbride)

Cons

  • Typekit is a paid service but it also has a free version.
  • JavaScript dependency, and one extra HTTP request for you.

Other web fonts solutions

Conclusion(s)

Now that you found out all the pros and cons, it’s up to you to choose the method that best suits your needs.

Let me know in the comments the solution you like most!

Posted by: Dhiraj kumar