Tag Archives: Application Services

Goodbye, Zen Coding. Hello, Emmet !

Back in 2009, Sergey Chikuyonok wrote an article to present a new way of writing HTML and CSS code. This revolutionary plugin, called Zen Coding, has helped many developers through the years and has now reached a new level.

Emmet, previously known as Zen Coding, is the most productive and time-saving text-editor plugin you will ever see. By instantly expanding simple abbreviations into complex code snippets, Emmet can turn you into a more productive developer.

For those who prefer to watch instead of read, here is a summary of my favorite tricks.

How Does It Work?

Let’s face it: writing HTML code takes time, with all of those tags, attributes, quotes, braces, etc. Of course, most text editors have code completion, which helps a lot, but you still have to do a lot of typing. Emmet instantly expands simple abbreviations into complex code snippets.

HTML Abbreviations

INITIALIZERS

Getting started with a new HTML document takes less than a second now. Just type !or html:5, hit “Tab,” and you’ll see an HTML5 doctype with a few tags to jumpstart your application.

Emmet Demonstration - Initializers

  • html:5 or ! for an HTML5 doctype
  • html:xt for an XHTML transitional doctype
  • html:4s for an HTML4 strict doctype

EASILY ADD CLASSES, IDS, TEXT AND ATTRIBUTES

Because Emmet’s syntax for describing elements is similar to CSS selectors, getting used to it is very easy. Try mixing an element’s name (e.g. p) with an identifier (e.g.p#description).

Emmet Demonstration - Classes and IDs

Also, you can combine classes and IDs. For example, p.bar#foo will output this:

<p id="foo"></p>

Now let’s see how to define content and attributes for your HTML elements. Curly brackets are used for content. So, h1{foo} will produce this:

<h1>foo</h1>

And square brackets are used for attributes. So, a[href=#] will generate this:

<a href="#"></a>

Emmet Demonstration - Texts and Attributes

NESTING

By nesting abbreviations, you can build a whole page using just one line of code. First, the child operator, represented by >, allows you to nest elements. The sibling operator, represented by +, lets you place elements near each other, on the same level. Finally, the new climb-up operator, represented by ^, allows you to climb up one level in the tree.

Emmet Demonstration - Nesting operators

GROUPING

To effectively take advantage of nesting without turning them into a confusing mess of operators, you’ll need to group some pieces of code. It’s like math — you just need to use parentheses around certain pieces. For example, (.foo>h1)+(.bar>h2) will output this:

<div>
  <h1></h1>
</div>
<div>
  <h2></h2>
</div>

Emmet Demonstration - Grouping

IMPLICIT TAG NAMES

To declare a tag with a class, just type div.item, and then it will generate <div></div>.

In the past, you could omit the tag name for a div; so, you just had to type .item and it would generate <div></div>. Now Emmet is more intelligent. It looks at the parent tag name every time you expand the abbreviation with an implicit name. So, if you declare .item inside of a <ul>, it will generate <li></li> instead of<div></div>.

Emmet Demonstration - Implicit tag names

Here’s a list of all implicit tag names:

  • li for ul and ol
  • tr for tabletbodythead and tfoot
  • td for tr
  • option for select and optgroup

MULTIPLICATION

You can define how many times an element should be outputted by using the *operator. So, ul>li*3 will produce:

<ul>
  <li></li>
  <li></li>
  <li></li>
</ul>

Emmet Demonstration - Multiplication

NUMBERING

What about mixing the multiplication feature with some item numbering? Just place the$ operator in the element’s name, the attribute’s name or the attribute’s value to output the number of currently repeated elements. If you write ul>li.item$*3, it will output:

<ul>
  <li></li>
  <li></li>
  <li></li>
</ul>

Emmet Demonstration - Numbering

Try It Now!

Why not try it right now? Go ahead: type in an Emmet HTML abbreviation, and hit theTab key.

CSS Abbreviations

VALUES

Emmet is about more than just HTML elements. You can inject values directly into CSS abbreviations, too. Let’s say you want to define a width. Type w100, and it will generate:

width: 100px;

Emmet Demonstration - Values

Pixel is not the only unit available. Try running h10p+m5e, and it will output:

height: 10%;
margin: 5em;

Here’s a list with a few aliases:

  • p → %
  • e → em
  • x → ex

EXTRA OPERATOR

You already know many intuitive abbreviations, such as @f, which produces:

@font-face {
  font-family:;
  src:url();
}

Some properties — such as background-imageborder-radiusfont@font-facetext-outlinetext-shadow — have some extra options that you can activate by using the +sign. For example, @f+ will output:

@font-face {
  font-family: 'FontName';
  src: url('FileName.eot');
  src: url('FileName.eot?#iefix') format('embedded-opentype'),
     url('FileName.woff') format('woff'),
     url('FileName.ttf') format('truetype'),
     url('FileName.svg#FontName') format('svg');
  font-style: normal;
  font-weight: normal;
}

Emmet Demonstration - Extra operator

FUZZY SEARCH

The CSS module uses fuzzy search to find unknown abbreviations. So, every time you enter an unknown abbreviation, Emmet will try to find the closest snippet definition. For example, ov:h and ov-h and ovh and oh will generate the same:

overflow: hidden;

Emmet Demonstration - Fuzzy Search

VENDOR PREFIXES

CSS3 is awesome, but those vendor prefixes are a real pain for all of us. Well, not anymore — Emmet has abbreviations for them, too. For example, the trs abbreviation will expand to:

-webkit-transform: ;
-moz-transform: ;
-ms-transform: ;
-o-transform: ;
transform: ;

Emmet Demonstration - Vendor Prefixes

You can also add prefixes to any kind of element. You just need to use the - prefix. So,-super-foo will expand to:

-webkit-super-foo: ;
-moz-super-foo: ;
-ms-super-foo: ;
-o-super-foo: ;
super-foo: ;

What if you don’t want all of those prefixes? No problem. You can define exactly which browsers to support. For example, -wm-trf will output:

-webkit-transform: ;
-moz-transform: ;
transform: ;
  • w → -webkit-
  • m → -moz-
  • s → -ms-
  • o → -o-

GRADIENTS

Speaking of annoying CSS3 features, we cannot forget gradients. Those long definitions with different notations can now be easily replaced with a concise, bulletproof abbreviation. Type lg(left, #fff 50%, #000), and the output will be:

background-image: -webkit-gradient(linear, 0 0, 100% 0, color-stop(0.5, #fff), to(#000));
background-image: -webkit-linear-gradient(left, #fff 50%, #000);
background-image: -moz-linear-gradient(left, #fff 50%, #000);
background-image: -o-linear-gradient(left, #fff 50%, #000);
background-image: linear-gradient(left, #fff 50%, #000);

Emmet Demonstration - Gradients

Try It Now!

Had enough of the animated GIFs? Go ahead — type an Emmet CSS abbreviation, and hit the Tab key.

Extras

LOREM IPSUM

Forget about those third-party services that generate “Lorem ipsum” text. Now you can do that right in your editor. Just use the lorem or lipsum abbreviations. You can specify how many words to generate. For instance, lorem10 will output:

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Libero delectus.

Emmet Demonstration - Lorem Ipsum

Also, lorem can be chained to other elements. So, p*3>lorem5 will generate:

<p>Lorem ipsum dolor sit amet.</p>
<p>Voluptates esse aliquam asperiores sunt.</p>
<p>Fugiat eaque laudantium explicabo omnis!</p>

Customization

Emmet offers a wide range of tweaks that you can use to fine-tune your plugin experience. There are three files you can edit to do this:

And A Lot More!

This is just the beginning. Emmet has a lot of other cool features, such as encoding and decoding images to data:URLupdating image sizes and incrementing and decrementing numbers.

Go check out the new website, the awesome documentation and the handy cheat sheet!

Supported Editors

If you are wondering, “Will it work in my text editor?,” The answer is, “Oh yes, my friend!” A lot of editors are supported, and I hope you find yours in the list below.

AND YOU?

What are your favorite tricks? Leave a comment below. Now it’s your turn to share your favorite tricks.

(al) (ea)

Introducing Jelly Navigation Menu: When Canvas Meets PaperJS

It’s our great pleasure to support active members of the Web design and development community. Today, we’re proud to present theJelly Navigation Menu that shows the power of PaperJS and TweenJS when used together. This article is yet another golden nugget of our series of various tools, libraries and techniques that we’ve published here on Smashing Magazine: LiveStylePrefixFree,FoundationSisyphus.jsGuideGuideGridpakJS Bin and CSSComb. — Ed.

There is no doubt that the Web helps designers and developers find the best inspiration and resources for their projects. Even though there are a bunch of different tutorials and tips available online, I feel that HTML5 canvas techniques are missing the most. Good news: I had the chance to fulfill this wide gap. In this article, I would like to share my experience and story of how I brought the “Jelly Navigation Menu” to life. Credits go toCapptivate.co and Ashleigh Brennan’s icons — they were my inspiration for this project.

BEFORE WE START

The source code for this project was originally written in CoffeeScript — I believe it’s a better way to express and share JavaScript code that way. I will refer to CoffeScript’s source in code sections within this post and you’ll also notice links to CodePens that have been rewritten in JavaScript and represent local parts of code as well. I recommend downloading the source code on GitHub so you can easily follow me while I explain the necessary code in detail.

I used PaperJS for the canvas graphics and TweenJS for the animations. Both of them tend to freak out some folks, but don’t worry, they are really intuitive and easy to understand. If you’d like to learn how to set up PaperJS and TweenJS environments, you can fork this cool bootstrap pen for online fun or this git repo if you want to experiment locally.


A preview of the Jelly Navigation Menu.

See Full Demo

First Step: Changing The Section Shape

Our first aim is to change the menu section shape by manipulating the curves. Every object is made up of anchor points. These points are connected with each other by curves. So each point has “In” and “Out” handles to define the location and direction of specific curves. Folks who work with vector editors should feel comfortable with this step.


In Paper.js, paths are represented by a sequence of segments that are connected by curves. A segment consists of a point and two handles, defining the location and direction of the curves.See the handles in action.

All we need to do is to change the handleOut position of the top-left and bottom-rightpoints. To achieve this, I wrote simple so-called “toppie” and “bottie” functions:

toppie:(amount)->
  @base.segments[1].handleOut.y = amount
  @base.segments[1].handleOut.x = (@wh/2)

bottie:(amount)->
  @base.segments[3].handleOut.y = amount
  @base.segments[3].handleOut.x = - @wh/2

# @wh/2 is section center.
# @base variable holds section's rectangle path.

It’s important to set the handle’s X position to exactly the middle of the section, so that the curve will turn out to be symmetrical.

See Demo #1

Second Step: Calculating The Scrolling Speed

So the next thing that needs to be done is to calculate the scrolling speed and direction, and then pass this data to the bottie and toppie functions. We can listen to the container’s scrolling event and determine the current scrolling position (in my case the “container” is a #wrapper element whereas it is a window object in the pen examples).

# get current scroll value
window.PaperSections.next = window.PaperSections.$container.scrollTop()

# and calculate the difference with previous scroll position
window.PaperSections.scrollSpeed = (window.PaperSections.next - window.PaperSections.prev)

# to make it all work, all we have left to do is to save current scroll position to prev variable
window.PaperSections.prev = window.PaperSections.next

This is repeated for every scrolling event. In this code snippet, window.PaperSections is just a global variable. I also made a few minor additions in my implementation:

  • A silly coefficient to increase scroll speed by multiplying it by 1.2 (just played around with it),
  • I sliced the scroll speed result by its maximum so that it is not larger thansectionHeight/2,
  • I also added a direction coefficient (it could be 1 or -1, you can change it indat.gui on the top right of the page). This way you can control the reaction direction of sections.

Here is the final code:

if window.PaperSections.i % 4 is 0
  direction = if window.PaperSections.invertScroll then -1 else 1
  window.PaperSections.next = window.PaperSections.$container.scrollTop()
  window.PaperSections.scrollSpeed = direction*window.PaperSections.slice 1.2*(window.PaperSections.next - window.PaperSections.prev), window.PaperSections.data.sectionheight/2
  window.PaperSections.prev = window.PaperSections.next
  window.PaperSections.i++

In this example, if window.PaperSections.i % 4 is 0 helps us react on every fourth scroll event — similar to a filter. That function lives in window.PaperSections.scrollControl.

That’s it! We’re almost done! It couldn’t be any easier, right? Try out the scrolling here.

See Demo #2

Step Three: Make It Jelly!

In this final step, we need to animate the toppie and bottie functions to 0 with TweenJS’ elastic easing everytime the scrolling stops.

3.1 DETERMINE WHEN SCROLLING STOPS

To do this, let’s add the setTimeout function to our window.PaperSections.scrollControlfunction (or scroll) with 50ms delay. Each time when the scrolling event fires up, the Timeout is cleared except for the last one, i.e. once scrolling stops, the code in our timeout will execute.

clearTimeout window.PaperSections.timeOut
window.PaperSections.timeOut = setTimeout ->
  window.PaperSections.$container.trigger 'stopScroll'
  window.PaperSections.i = 0
  window.PaperSections.prev = window.PaperSections.$container.scrollTop()
    , 50

The main focus here is the window.PaperSections.$container.trigger stopScroll event. We can subscribe to it and launch the animation appropriately. The other two lines of code are simply being used to reset helper variables for later scrollSpeed calculations.

See Demo #3

3.2 ANIMATE POINT’S HANDLEOUT TO “0”

Next, we’ll write the translatePointY function to bring our jelly animation to life. This function will take the object as a parameter with the following key-value sets:

{
  // point to move (our handleOut point)
  point: @base.segments[1].handleOut,

  // destination point
  to: 0,

  // duration of animation
  duration: duration
}

The function body is made up of the following:

translatePointY:(o)->
  # create new tween(from point position) to (options.to position, with duration)
  mTW = new TWEEN.Tween(new Point(o.point)).to(new Point(o.to), o.duration)

  # set easing to Elastic Out
  mTW.easing TWEEN.Easing.Elastic.Out

  # on each update set point's Y to current animation point
  mTW.onUpdate ->
    o.point.y = @y

  # finally start the tween
  mTW.start()

The TWEEN.update() function also has to be added to every frame of the PaperJS animation loop:

onFrame = ->
  TWEEN.update()

Also, we need to stop all animations on scrolling. I added the following line to the scroll listener function:

TWEEN.removeAll()

Finally, we need to subscribe to the stopScroll event and launch the animations by calling our translatePointY function:

window.PaperSections.$container.on 'stopScroll', =>
  # calculate animation duration
  duration = window.PaperSections.slice(Math.abs(window.PaperSections.scrollSpeed*25), 1400) or 3000

  # launch animation for top left point
  @translatePointY(
    point:      @base.segments[1].handleOut
    to:           0
    duration: duration
  ).then =>
    # clear scroll speed variable after animation has finished
    # without it section will jump a little when new scroll event fires
    window.PaperSections.scrollSpeed = 0

  # launch animation for bottom right point
  @translatePointY
    point:      @base.segments[3].handleOut
    to:           0
    duration: duration

Et voilà!

See Demo #4

 

Note: In my source code of the translatePointY function, I added a deferred object for chaining, optional easing and onUpdate function. It is omitted here for the sake of simplicity. 

In Conclusion

Last but not least, a class for the sections has to be added. Of course, you can make as many instances of it as you like; you just need to define initial Y offset and colors. Also, you will need to make sure that the section in your layout has the same height as the section in canvas. Then we can just apply translated3d to both on the scroll event and animations. This will cause HTML sections to move properly, just like the canvas sections, and hence produce a realistic animation.

HTML Sections

The reason why we need to use translate3d instead of translateY is to make sure that Webkit rendering engines use hardware acceleration while rendering them, so we do not drop out of the 60fps animation budget. But keep your eyes wide open if your sections contain any text. 3D transforms will drop anti-aliasing from subpixel to grayscale, so it may look a bit blurry!

Semantic CSS With Intelligent Selectors

“Form ever follows function. This is the law.” So said the architect and “father of skyscrapers” Louis Sullivan. For architects not wishing to crush hundreds of innocent people under the weight of a colossal building, this rule of thumb is pretty good. In design, you should always lead with function, and allow form to emerge as a result. If you were to lead with form, making your skyscraper look pretty would be easier, but at the cost of producing something pretty dangerous.

So much for architects. What about front-end architects — or “not real architects,” as we are sometimes known? Do we abide by this law or do we flout it?

With the advent of object-oriented CSS (OOCSS), it has become increasingly fashionable to “decouple presentation semantics from document semantics.” By leveraging the undesignated meanings of classes, it is possible to manage one’s document and the appearance of one’s document as curiously separate concerns.

Overthinking how a functional thing should look.

In this article, we will explore an alternative approach to styling Web documents, one that marries document semantics to visual design wherever possible. With the use of “intelligent” selectors, we’ll cover how to query the extant, functional nature of semantic HTML in such a way as to reward well-formed markup. If you code it right, you’ll get the design you were hoping for.

If you are like me and have trouble doing or thinking about more than one thing at a time, I hope that employing some of these ideas will make your workflow simpler and more transferable between projects. In addition, the final section will cover a more reactive strategy: We’ll make a CSS bookmarklet that contains intelligent attribute selectors to test for bad HTML and report errors using pseudo-content.

Intelligent Selectors

With the invention of style sheets came the possibility of physically separating document code from the code used to make the document presentable. This didn’t help us to write better, more standards-aware HTML any more than the advent of the remote control resulted in better television programming. It just made things more convenient. By being able to style multiple elements with a single selector (p for paragraphs, for instance), consistency and maintenance became significantly less daunting prospects.

television remote reading DRIVEL

The p selector is an example of an intelligent selector in its simplest form. The pselector is intelligent because it has innate knowledge of semantic classification. Without intervention by the author, it already knows how to identify paragraphs and when to style them as such — simple yet effective, especially when you think of all of the automatically generated paragraphs produced by WYSIWYG editors.

So, if that’s an intelligent selector, what’s an unintelligent one? Any selector that requires the author to intervene and alter the document simply to elicit a stylistic nuance is an unintelligent selector. The class is a classic unintelligent selector because it is not naturally occurring as part of semantic convention. You can name and organize classes sensibly, but only with deliberation; they aren’t smart enough to take care of themselves, and browsers aren’t smart enough to take care of them for you.

Unintelligent selectors are time-intensive because they require styling hooks to be duplicated case by case. If we didn’t have p tags, we’d have to use unintelligent selectors to manufacture paragraphs, perhaps using .paragraph in each case. One of the downsides of this is that the CSS isn’t portable — that is, you can’t apply it to an HTML document without first going through the document and adding the classes everywhere they are required.

class selector called paragraph

Unintelligent selectors at times seem necessary, or at least easier, and few of us are willing to rely entirely on intelligent selectors. However, some unintelligent selectors can become “plain stupid” selectors by creating a mismatch between document structure and presentation. I’ll be talking about the alarming frequency with which the unintelligent .button selector quickly becomes plain stupid.

VIVE LA DIFFÉRENCE

Intelligent selectors are not confined just to the basic elements offered to us in HTML’s specification. To build complex intelligent selectors, you can defer to combinations ofcontext and functional attribution to differentiate basic elements. Some elements, such as <a>, have a multitude of functional differences to consider and exploit. Other elements, such as <p>, rarely differ in explicit function but assume slightly different roles according to context.

header p {
   /* styles for prologic paragraphs */
}

footer p {
   /* styles for epilogic paragraphs */
}

Simple descendent selectors like these are extremely powerful because they enable us to visually disclose different types of the same element without having to physically alter the underlying document. This is the whole reason why style sheets were invented: to facilitate physical separation without breaking the conceptual reciprocity that should exist between document and design.

a semantic heirarchy of needs: what it is, how it functions, where it is

Inevitably, some adherents of OOCSS treat the descendent selector with some suspicion, with the more zealous insisting on markup such as the example below, found in BEM’s “Definitions” documentation.

<ul>
  <li>…</li>
  <li>…</li>
</ul>

I won’t cover contextual selectors any further because, unless you have a predilection for the kind of overprescription outlined above, I’m sure you already use them every day. Instead, we’ll concentrate on differentiation by function, as described in attributes and by attribute selectors.

Hyperlink Attributes

Even those who advocate for conceptual separation between CSS and HTML are happy to concede that some attributes — most attributes besides classes and custom data attributes, in fact — have an important bearing on the internal functioning of the document. Without href, your link won’t link to anything. Without type, the browser won’t know what sort of input to render. Without title, your abbr could be referring to either the British National Party or Banco Nacional de Panama.

Some of these attributes may improve the semantic detail of your document, while others are needed to ensure the correct rendering and functioning of their subject elements. If they’re not there, they should be, and if they are there, why not make use of them? You can’t write CSS without writing HTML.

THE REL ATTRIBUTE

The rel attribute emerged as a standard for link relations, a method of describing some specific purpose of a link. Not all links, you see, are functionally alike. Thanks to WordPress’ championing, rel="prev" and rel="next" are two of the most widely adopted values, helping to describe the relationship between individual pages of paginated blog content. Semantically, an a tag with a rel attribute is still an a tag, but we are able to be more specific. Unlike with classes, this specificity is semantically consequential.

The rel attribute should be used where appropriate because it is vindicated by HTML’sfunctional specification and can therefore be adopted by various user agents to enhance the experience of users and the accuracy of search engines. How, then, do you go about styling such links? With simple attribute selectors, of course:

[rel="prev"] {
  /* styling for "previous links" */
}

[rel="next"] {
  /* styling for "next" links */
}

Attribute selectors like these are supported by all but the most archaic, clockwork browsers, so that’s no reason not to use them anywhere the attributes exist. In terms of specificity, they have the same weight as classes. No woe there either, then. However, I recall it being suggested that we should decouple document and presentation semantics. I don’t want to lose the rel attributes (Google has implemented them, for one thing), so I’d better put an attribute that means nothing on there as well and style the element via that.

  <a href="/previous-article-snippet/" rel="prev">previous page</a>

The first thing to note here is that the only part of the element above that does not contribute to the document’s semantics is the class. The class, in other words, is the only thing in the document that has nothing functionally to do with it. In practice, this means that the class is the only thing that breaks with the very law of separation that it was employed to honor: It has a physical presence in the document without contributing to the document’s structure.

OK, so much for abstraction, but what about maintenance? Accepting that we’ve used the class as our styling hook, let’s now examine what happens when some editing or refactoring has led us to remove some attributes. Suppose we’ve used some pseudo-content to place a left-pointing arrow before the [rel="prev"] link’s text:

.prev:before {
  content: '2190'; /* encoding for a left-pointing arrow ("←") */
}

previous link with arrow

Removing the class will remove the pseudo-content, which in turn will remove the arrow (obviously). But without the arrow, nothing remains to elucidate the link’s extantprev relationship. By the same token, removing the rel attribute will leave the arrow intact: The class will continue to manage presentation, all the time disguising thenonexistence of a stated relationship in the document. Only by applying the style directly, via the semantic attribute that elicits it, can you keep your code and yourself honest and accurate. Only if it’s really there, as a function of the document, should you see it.

Attribute Substrings

I can imagine what you’re thinking: “That’s cute, but how many instances are there really for semantic styling hooks like these on hyperlinks? I’m going to have to rely on classes at some point.” I dispute that. Consider this incomplete list of functionally disimilar hyperlinks, all using the a element as their base:

  • links to external resources,
  • links to secure pages,
  • links to author pages,
  • links to help pages,
  • links to previous pages (see example above),
  • links to next pages (see example above again),
  • links to PDF resources,
  • links to documents,
  • links to ZIP folders,
  • links to executables,
  • links to internal page fragments,
  • links that are really buttons (more on these later),
  • links that are really buttons and are toggle-able,
  • links that open mail clients,
  • links that cue up telephone numbers on smartphones,
  • links to the source view of pages,
  • links that open new tabs and windows,
  • links to JavaScript and JSON files,
  • links to RSS feeds and XML files.

That’s a lot of functional diversity, all of which is understood by user agents of all sorts. Now consider that in order for all of these specific link types to function differently, they must have mutually differential attribution. That is, in order to function differently, they must be written differently; and if they’re written differently, they can be styled differently.

In preparing this article, I created a proof of concept, named Auticons. Auticons is anicon font and CSS set that styles links automatically. All of the selectors in the CSS file are attribute selectors that invoke styles on well-formed hyperlinks, without the intervention of classes.

art_auticons

In many cases, Auticons queries a subset of the href value in order to determine the function of the hyperlink. Styling elements according to the way their attribute values begin or end or according to what substring they contain throughout the value is possible. Below are some common examples.

THE SECURE PROTOCOL

Every well-formed (i.e. absolute) URL begins with a URI scheme followed by a colon. The most common on the Web is http:, but mailto: (for SMTP) and tel: (which refers to telephone numbers) are also prevalent. If we know how the href value of the hyperlink is expected to begin, we can exploit this semantic convention as a styling hook. In the following example for secure pages, we use the ^= comparator, which means “begins with.”

a[href^="https:"] {
   /* style properties exclusive to secure pages */
}

a link to a secure page with a lock icon

In Auticons, links to secure pages become adorned with a padlock icon according to a specific semantic pattern, identifiable within the href attribute. The advantages of this are as follows:

  • Links to secure pages — and only secure pages — are able to resemble links to secure pages by way of the padlock icon.
  • Links to secure pages that cease to be true links to secure pages will lose thehttps protocol and, with it, the resemblance.
  • New secure pages will adopt the padlock icon and resemble links to secure pages automatically.

This selector becomes truly intelligent when applied to dynamic content. Because secure links exist as secure links even in the abstract, the attribute selector can anticipate their invocation: As soon as an editor publishes some content that contains a secure link, the link resembles a secure one to the user. No knowledge of class names or complex HTML editing is required, so even simple Markdown will create the style:

[Link to secure page](https://payment.example.com/)

Note that using the [href^="https:"] prefix is not infallible because not all HTTPS pages are truly secure. Nonetheless, it is only as fallible as the browser itself. Major browsers all render a padlock icon natively in the address bar when displaying HTTPS pages.

PayPal secure page

FILE TYPES

As promised, you can also style hyperlinks according to how their href value ends. In practice, this means you can use CSS to indicate what type of file the link refers to. Auticons supports .txt.pdf.doc.exe and many others. Here is the .zip example, which determines what the href ends with, using $=:

[href$=".zip"]:before,
[href$=".gz"]:before {
   content: 'E004'; /* unicode for the zip folder icon */
}

COMBINATIONS

You know how you can get all object-oriented and use a selection of multiple classes on elements to build up styles? Well, you can do that automatically with attribute selectors, too. Let’s compare:

/* The CSS for the class approach */

.new-window-icon:after {
   content: '[new window icon]';
}

.twitter-icon:before {
  content: '[twitter icon]';
}

/* The CSS for the attribute selector approach */

[target="_blank"]:after {
   content: '[new window icon]';
}

[href*="twitter.com/"]:before {
  content: '[twitter icon]';
}

(Note the *= comparator, which means “contains.” If the value string contains the substring twitter.com/, then the style will be honored.)

<!-- The HTML for the class approach -->

<a href="http://twitter.com/heydonworks" target="_blank">@heydonworks</a>

<!-- The HTML for the attribute selector approach -->

<a href="http://twitter.com/heydonworks" target="_blank">@heydonworks</a>

A twitter link with icons to show that it goes to twitter and is external

Any content editor charged with adding a link to a Twitter page now needs to know only two things: the URL (they probably know the Twitter account already) and how to open links in new tabs (obtainable from a quick Google search).

INHERITANCE

Some unfinished business: What if we have a link that does not match any of our special attribute selectors? What if a hyperlink is just a plain old hyperlink? The selector is an easy one to remember, and performance fanatics will be pleased to hear that it couldn’t be any terser without existing at all.

A basic anchor selector (a)

Flippancy aside, let me assure you that inheritance within the cascade works with attribute selectors just as it does with classes. First, style your basic a — perhaps with atext-decoration: underline rule to keep things accessible; then, progressively enhance further down the style sheet, using the attribute selectors at your disposal. Browsers such as Internet Explorer (IE) 7 do not support pseudo-content at all. Thanks to inheritance, at least the links will still look like links.

a {
  color: blue;
  text-decoration: underline;
}

a[rel="external"]:after {
   content: '[icon for external links]';
}

Actual Buttons Are Actual

In the following section, we’ll detail the construction of our CSS bookmarklet for reporting code errors. Before doing this, let’s look at how plain stupid selectors can creep into our workflow in the first place.

Adherents of OOCSS are keen on classes because they can be reused, as components. Hence, .button is preferable to #button. I can think of one better component selector for button styles, though. Its name is easy to remember, too.

button element selector

The <button> element represents a button.

– W3C Wiki

Topcoat is an OOCSS BEM-based UI framework from Adobe. The CSS for Topcoat’s various button styles is more than 450 lines if you include the comment blocks. Each of these comment blocks suggests applying your button style in a manner similar to this introductory example:

   <a>Button</a>

This example is not a button. No, sir. If it were a button, it would be marked up using<button>. In fact, in every single browser known to man, if it were marked up as a button and no author CSS was supplied, you could count on it looking like a button by default. It’s not, though; it’s marked up using <a>, which makes it a hyperlink — a hyperlink, in fact, that lacks an href, meaning it isn’t even a hyperlink. Technically, it’s just a placeholder for a hyperlink that you haven’t finished writing yet.

Dog in a shark costume
A dog in a shark costume does not a shark make. (Image: reader of the pack)

The examples in Topcoat’s CSS are only examples, but the premise that the class defines the element and not the HTML is deceptive. No amount of class name modification via “meaningful hyphenation” can make up for this invitation to turn your unintelligent selector into a plain stupid one and to just code stuff wrong.

Update: Since writing this article, Topcoat.io has replaced these examples with <button> examples. This is great! However, I still have my reservations about the way the examples expound the use of the .is-disabled class while omitting the properdisabled attribute. To hear both sides, find my conversation with the Topcoat representative in the comments. For further examples of OOCSS-facilitated web standards mishaps, look no further than semantic-ui.com. The “standard button” in their examples is a <div> containing an empty <i>.

SEE NO EVIL, HEAR NO EVIL

“If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.”

A link that resembles a button and triggers button-like JavaScript events is, to many, a button. However, this only means that it has passed the first two stages of the “duck test.” For all users to be able to apply inductive reasoning and discern the button as such, it must also quack like one. Because it remains a link, it will be announced by screen readers as “link,” meaning that your allegorical skyscraper is not wheelchair-accessible. Avoiding this kind of unnecessary confusion for assistive technology users is not a pursuit of semantic perfection but a responsibility we should undertake for real benefit.

Nonetheless, some will insist on using a as the basis of their buttons. Hyperlinks are (slightly) easier to restyle consistently, after all. If a is the element of choice, then there is only one way to make it a close-to-true button in the accessibility layer. You guessed it: You must apply another meaningful attribute in the form of a WAI ARIA role. To ensure that a hyperlink element looks like a button for good reason, apply only the following attribute selector.

[role="button"] {
   /* semantic CSS for modified elements that are announced as “button” in assistive technologies */
}

Quality Assurance With Attribute Selectors

“CSS gives so much power to the class attribute, that authors could conceivably design their own “document language” based on elements with almost no associated presentation (such as DIV and SPAN in HTML) and assigning style information through the “class” attribute. Authors should avoid this practice since the structural elements of a document language often have recognized and accepted meanings.”

– “Selectors,” CSS Level 2, W3C

The reason we have two elements — a and button — is to semantically demarcate two entirely different types of functional interaction. While the hyperlink denotes a means to go somewhere, the button is intended as the instigator of an event or action. One is about traversal, the other about transformation. One facilitates disengagement, the other engagement.

To make sure we don’t do anything too daft and get our links and buttons muddled up, we will now build a CSS bookmarklet that uses intelligent attribute selectors to test the validity and quality of the two respective elements.

Inspired partly by Eric Meyer’s post and taking a few cues from DiagnostiCSS, this style sheet will combine attribute selectors and the :not selector (or negation pseudo-class) to highlight problems in the HTML. Unlike these other two implementations, it will write an error to the screen using pseudo-content. Each error will be written in Comic Sansagainst a pink background.

By connecting function directly to form, we see that ugly markup results in ugly CSS. Consider this the revenge of an abused document, exacted on its designer. To try it out, drag revenge.css to your bookmarks, and click the bookmark to trigger it on any page that you fancy. Note: It won’t currently work for pages that are served over https.

REVENGE.CSS
Drag to your bookmarks bar.

RULE 1

“If it’s a hyperlink, it should have an href attribute.”

a:not([href]):after {
   content: 'Do you mean for this to be a link or a button, because it does not link to anything!';
   display: block !important;
   background: pink !important;
   padding: 0.5em !important;
   font-family: 'comic sans ms', cursive !important;
   color: #000 !important;
   font-size: 16px !important;
}

Notes: In this example, we are testing not the attribute’s value, but whether the attribute exists in the first place — that is, whether [href] matches any element with anhref attribute. This test is only appropriate on hyperlinks, hence the a prefix. The rule reads like, “For every a element that is not also an [href] element, append some pseudo-content with an error notice.”

RULE 2

“If it’s a hyperlink and has an href attribute, it should have a valid value.”

a[href=""]:after, a[href$="#"]:after, a[href^="javascript"]:after {
   content: 'Do you mean for this link to be a button, because it does not go anywhere!';
   /*... ugly styles ...*/
}

Notes: If the href is empty, ends in a # or is using JavaScript, it’s probably being used as a button without the correct button element. Note that I am using “starts withjavascript.” Standard practice for voiding hrefs is to use javascript:void(0), but we can’t depend on that always being written in the same way (with or without a space after the colon, for example).

RULE 3

“If it uses a button class, it should be a button — at least in the accessibility layer.”

.button:not(button):not([role="button"]):not([type="button"]):not([type="submit"]):not([type="reset"]):after,
.btn:not(button):not([role="button"]):not([type="button"]):not([type="submit"]):not([type="reset"]):after,
a[class*="button"]:not([role="button"]):after {
   content: 'If you are going to make it look like a button, make it a button, damn it!';
   /*... ugly styles ...*/
}

Notes: In this example, we’re demonstrating how you can chain negation when testing for attributes. Each selector reads like this: “If the element has a class that says it’s a button but it’s not a button element and it doesn’t have the correct role to make it a button in the accessibility layer and it’s not an input being used as a button, then… well, you’re lying.” I’ve had to use [class*="button"] to catch the many Topcoat class variations (62 in total!) that fail to enforce actual buttons on hyperlinks. I’ve noticed that some authors use button-container and the like on parent elements, which is why thea qualifier is included to avoid false positives. You may recognize the .btn class from Twitter Bootstrap, which (if you’ve read the component’s documentation carefully) you’ll know is also unsure about whether links or buttons are buttons.

RULE 4

“If it is an a element with role="button", then it should link to somewhere when JavaScript is off.”

a[role="button"]:not([href*="/"]):not([href*="."]):not([href*="?"]):after {
   content: 'Either use a link fallback, or just use a button element.';
   /*... ugly styles ...*/
}

Notes: We can be fairly sure that hrefs that do not include one of /. (usually to precede a file extension) or ? (to start a query string) are probably bogus. Getting links to act as buttons and return: false when JavaScript is on is fine — fine, that is, if they have a page to go to when JavaScript is off. In fact, it’s the only legitimate reason I can think of not to use <button> instead.

RULE 5

“You can’t disable a hyperlink.”

a.button[class*="disabled"]:after,
a.btn.disabled:after,
a[class*="button"][class*="disabled"]:after {
   content: 'You cannot disable a hyperlink. Use a button element with disabled="disabled".';
   /*... ugly styles ...*/
}

Notes: Even ancient user agents understand the disabled attribute, so use it with an appropriate element in a compliant way. You can concatenate attribute selectors just as you can concatenate classes: In the last of the three selectors, we’re saying, “If it’s a link that contains the substring button and the substring disabled, then print an error message.” Twitter Bootstrap uses the second form, .btn.disabled, in its style sheet, but not with the a prefix. We’ll only consider it an error if used on hyperlinks.

RULE 6

“Buttons in forms should have explicit types.”

form button:not([type]):after {
	content: 'Is this a submit button, a reset button or what? Use type="submit", type="reset" or type="button"';
}

Notes: We need to determine whether buttons within forms have explicit types, because some browsers will treat any button in this context without a specified type astype="submit". We want to be absolutely sure that the form won’t submit if our button has a different purpose.

RULE 7

“Both hyperlinks and buttons should have some sort of content or an ARIA label.”

a:empty:not([aria-label]):not([aria-labelledby]):after,
button:empty:not([aria-label]):not([aria-labelledby]):after,
button:not([aria-label]):not([aria-labelledby]) img:only-child:not([alt]):after,
a:not([aria-label]):not([aria-labelledby]) img:only-child:not([alt]):after {
   content: 'All buttons and links should have text content, an image with alt text or an ARIA label';
   /*... ugly styles ...*/
}

Notes: Buttons and links that don’t include any kind of direction for their usage — in either textual or graphical form — are pretty bogus. These final two selectors are perhaps the most complex I’ve ever written. For the hyperlink version, the selector reads something like this: “If it is a hyperlink that does not have either an aria-labelattribute or an aria-labelledby attribute and it contains only an image as content but this image does not have an alt attribute, then write the ugly error message.” Also, note the use of the :empty selector. Arguably, no element that is not self-closing should ever be left empty.

Ten points to the first person using revenge.css who can tell me where I’ve broken my own rule in this very article. Trust me, the error is definitely there.

Conclusion

The reason I use the kinds of selectors and patterns described above is not to try something different or to have something new to write about. Attribute selectors aren’t, by themselves, anything new anyway. IE 6 is the only browser that doesn’t support them. The reason I use them is because I simply do not have the time or mental capacity to “do” HTML and CSS in parallel. My brain just isn’t good enough for that. The reason I style my page headers with [role="banner"] and not .page-header is because that’s the only way I’ll know — upon seeing the intended visual effect — that I’ve put thenavigable landmark in place. How else does one keep track? You can’t just leave it to testing, because then it’s usually too late.

There’s no such thing as semantic CSS. There’s only semantic HTML and its visible form. In this article I have tried to demonstrate that, by coupling the function and form of Web pages directly, you can create mechanisms for reward and punishment. On the one hand, you can set up selectors that invoke visual motifs only when the suitable markup is used. On the other hand, you can query the markup for bad patterns and erode the visual design as a commitment to the underlying ugly truth.

It’s true that not all the styling hooks in your arsenal will likely ever be uniformly semantic or intelligent. Classes are often desirable as polyfills for much needed elements or attributes that have yet to be standardized. That’s how .footer became<footer> and type="text" (with a bunch of JavaScript) became type="url". Other times, they are helpful for doing non-semantic layout scaffolding with grid frameworks and the like.

However, if you are committed to giving CSS its own completely separate logic, then you are bound to create unnecessary arguments between form and function. In this eventuality, only constant vigilance can protect against inaccessibility and invalidity. To make matters worse, trying to manufacture pseudo-semantics purely with classes makes it easy to fall into one of those interminable discussions over what makes a semantic class name. You’ll start spending less time using the remote to control the TV and more time just sitting there, contemplating the remote control held in your hand.

Life is too short.

(al)

Thinking Inside The Box With Vanilla JavaScript

During the past four or five years of blogging regularly and doing research for other writing projects, I’ve come across probably thousands of articles on JavaScript.

To me, it seems that a big chunk of these articles can be divided into two very general categories:

  1. jQuery;
  2. Theory and concept articles focused on things like IIFEsclosures and design patterns.

Yes, I’ve likely stumbled upon a ton of other articles that don’t fall into either of these categories or that are more specific. But somehow it feels that most of the ones that really get pushed in the community fall under one of the two categories above.

I think those articles are great, and I hope we see more of them. But sometimes the simplest JavaScript features are sitting right under our noses and we just haven’t had a lot of exposure to them. I’m talking about native, more-or-less cross-browser features that have been in the language for some time.

So, in this article, I won’t be talking about jQuery, and I won’t be looking at structural code concepts or patterns. Instead, I’m going to introduce you to some pure JavaScript features that you can use today and that you might not have ever considered before.

insertAdjacentHTML()

Years ago, Microsoft introduced a method called insertAdjacentHTML() as a way to insert a specified string of text as HTML or XML into a specific place in the DOM. This feature has been available in Internet Explorer (IE) since version 4. Let’s see how it works.

Suppose you have the following HTML:

<div id="box1">
    <p>Some example text</p>
</div>
<div id="box2">
    <p>Some example text</p>
</div>

And suppose you want to insert another snippet of HTML between #box1 and #box2. You can do this quite easily using insertAdjacentHTML():

var box2 = document.getElementById("box2");
box2.insertAdjacentHTML('beforebegin', '<div><p>This gets inserted.</p></div>');

With that, the generated DOM ends up like this:

<div id="box1">
    <p>Some example text</p>
</div>
<div><p>This gets inserted.</p></div>
<div id="box2">
    <p>Some example text</p>
</div>

The insertAdjacentHTML() method takes two parameters. The first defines where you want to place the HTML, relative to the targeted element (in this case, the #box2element). This may be one of the following four string values:

  • beforebegin
    The HTML would be placed immediately before the element, as a sibling.
  • afterbegin
    The HTML would be placed inside the element, before its first child.
  • beforeend
    The HTML would be placed inside the element, after its last child.
  • afterend
    The HTML would be placed immediately after the element, as a sibling.

Again, these are string values, not keywords, so they must be placed inside of single or double quotes.

The second parameter is the string you want to insert, also placed in quotes (or else it would be a variable holding a string that was previously defined). Note that it should be a string, not a DOM element or element collection; so, it could just be text, with no actual markup.

insertAdjacentHTML() has, as outlined in a post on Mozilla Hacks, a couple of advantages over something more conventional, like innerHTML(): It does not corrupt the existing DOM elements, and it performs better.

And if you’re wondering why this one hasn’t received a lot of attention so far, despite being well supported in all in-use versions of IE, the reason is probably that, as mentioned in the Mozilla Hacks article, it was not added to Firefox until version 8. Because all other major browsers support this, and Firefox users have been auto-updating since version 5, it’s quite safe to use.

For more on this method:

getBoundingClientRect()

You can obtain the coordinates and, by extension, the dimensions of any element on the page using another lesser-known method, the getBoundingClientRect() method.

Here’s an example of how it might be used:

var box = document.getElementById('box'),
    x, y, w;

x = box.getBoundingClientRect().left;
y = box.getBoundingClientRect().top;

if (box.getBoundingClientRect().width) {
  w = box.getBoundingClientRect().width; // for modern browsers
} else {
  w = box.offsetWidth; // for oldIE
}

console.log(x, y, w);

Here, we’ve targeted an element with an ID of box, and we’re accessing three properties of the getBoundingClientRect() method for the #box element. Here’s a summary of six fairly self-explanatory properties that this method exposes:

  • top
    How many pixels the top edge of the element is from the topmost edge of the viewport
  • left
    How many pixels the left edge of the element is from the leftmost edge of the viewport
  • right
    How many pixels the right edge of the element is from the leftmost edge of the viewport
  • bottom
    How many pixels the bottom edge of the element is from the topmost edge of the viewport
  • width
    The width of the element
  • height
    The height of the element

All of these properties are read-only. And notice that the coordinate properties (top,leftright and bottom) are all relative to the top-left of the viewport.

What about the if/else in the example from above? IE 6 to 8 don’t support the widthand height properties; so, if you want full cross-browser support for those, you’ll have to use offsetWidth and/or offsetHeight.

As with insertAdjacentHTML(), despite the lack of support for width and height, this method has been supported in IE since ancient times, and it has support everywhere else that’s relevant, so it’s pretty safe to use.

I will concede something here: Getting the coordinates of an element using offset-based values (such as offsetWidth) is actually faster than using getBoundingClientRect(). Note, however, that offset-based values will always round to the nearest integer, whereas getBoundingClientRect()’s properties will return fractional values.

For more info:

The <table> API

If you’ve ever manipulated elements on the fly with JavaScript, then you’ve likely used methods such as createElementremoveChildparentNode and related features. And you can manipulate HTML tables in this way, too.

But you may not realize that there is a very specific API for creating and manipulating HTML tables with JavaScript, and it has very good browser support. Let’s take a quick look at some of the methods and properties available with this API.

All of the following methods are available to be used on any HTML table element:

  • insertRow()
  • deleteRow()
  • insertCell()
  • deleteCell()
  • createCaption()
  • deleteCaption()
  • createTHead()
  • deleteTHead()

And then there are the following properties:

  • caption
  • tHead
  • tFoot
  • rows
  • rows.cells

With these features, we can create an entire table, including rows, cells, a caption and cell content. Here’s an example:

var table = document.createElement('table'),
    tbody = document.createElement('tbody'),
    i, rowcount;

table.appendChild(tbody);

for (i = 0; i <= 9; i++) {
  rowcount = i + 1;
  tbody.insertRow(i);
  tbody.rows[i].insertCell(0);
  tbody.rows[i].insertCell(1);
  tbody.rows[i].insertCell(2);
  tbody.rows[i].cells[0].appendChild(document.createTextNode('Row ' + rowcount + ', Cell 1'));
  tbody.rows[i].cells[1].appendChild(document.createTextNode('Row 1, Cell 2'));
  tbody.rows[i].cells[2].appendChild(document.createTextNode('Row 1, Cell 3'));
}

table.createCaption();
table.caption.appendChild(document.createTextNode('A DOM-Generated Table'));

document.body.appendChild(table);

The script above combines some customary core DOM methods with methods and properties of the HTMLTableElement API. The same code written without the table API might be considerably more complex and, thus, harder to read and maintain.

Once again, these table-related features have support all the way back to IE 7 (and probably earlier) and everywhere else that’s relevant, so feel free to use these methods and properties where you see fit.

For more info:

Wrapping Up

This discussion of specific native JavaScript features has been a reminder of sorts. We can easily become comfortable with the features of a language that we know well, without looking deeper into the language’s syntax for simpler and more maintainable ways to solve our problems.

So, from time to time, look inside the box, so to speak. That is, investigate all that vanilla JavaScript has to offer, and try not to rely too much on plugins and libraries, which can unnecessarily bloat your code.

(Credits of image on front page: nyuhuhuu)

(al ea)

Challenging CSS Best Practices

When it comes to CSS, I believe that the sacred principle of “separation of concerns” (SoC) has lead us to accept bloat, obsolescence, redundancy, poor caching and more. Now, I’m convinced that the only way to improve how we author style sheets is by moving away from this principle.

For those of you who have never heard of the SoC principle in the context of Web design, it relates to something commonly known as the “separation of the three layers”:

  • structure,
  • presentation,
  • behavior.

It is about dividing these concerns into separate resources: an HTML document, one or more cascading style sheets and one or more JavaScript files.

But when it comes to the presentational layer, “best practice” goes way beyond the separation of resources. CSS authors thrive on styling documents entirely through style sheets, an approach that has been sanctified by Dave Shea’s excellent project CSS Zen Garden. CSS Zen Garden is what most — if not all — developers consider to be thestandard for how to author style sheets.

The Standard

To help me illustrate issues related to today’s best practices, I’ll use a very common pattern: the media object. Its combination of markup and CSS will be our starting point.

MARKUP

In our markup, a wrapper (div.media) contains an image wrapped in a link (a.img), followed by a div (div.bd):

<div>
  <a href="http://twitter.com/thierrykoblentz">
        <img src="thierry.jpg" alt="me" width="40" />
  </a>
  <div>
    @thierrykoblentz 14 minutes ago
  </div>
</div>

CSS

Let’s give a 10-pixel margin to the wrapper and style both the wrapper and div.bd asblock-formatting contexts (BFC). In other words, the wrapper will contain the floated link, and the content of div.bd will not wrap around said link. A gutter between the image and text is created with a 10-pixel margin (on the float):

.media {
    margin: 10px;
}
.media,
.bd {
    overflow: hidden;
    _overflow: visible;
    zoom: 1;
}
.media .img {
    float: left;
    margin-right: 10px;
}
.media .img img {
    display: block;
}

RESULT

Here is the presentation of the wrapper, with the image in the link and the blob of text:


me
 

@thierrykoblentz 14 minutes ago

 

A NEW REQUIREMENT COMES IN

Suppose we now need to be able to display the image on the other side of the text as well.

MARKUP

Thanks to the magic of BFC, all we need to do is change the styles of the link. For this, we use a new class, imgExt.

<div>
    <a href="http://twitter.com/thierrykoblentz">
        <img src="thierry.jpg" alt="me" width="40" />
  </a>
  <div>
    @thierrykoblentz 14 minutes ago
  </div>
</div>

CSS

We’ll add an extra rule to float the link to the right and change its margin:

.media {
    margin: 10px;
}
.media,
.bd {
    overflow: hidden;
    _overflow: visible;
    zoom: 1;
}
.media .img {
    float: left;
    margin-right: 10px;
}
.media .img img {
    display: block;
}
.media .imgExt {
    float: right;
    margin-left: 10px;
}

RESULT

The image is now displayed on the opposite side:


me
 

@thierrykoblentz 14 minutes ago

 

ONE MORE REQUIREMENT COMES IN

Suppose we now need to make the text smaller when this module is inside the right rail of the page. To do that, we create a new rule, using #rightRail as a contextual selector:

MARKUP

Our module is now inside a div#rightRail container:

<div id="rightRail">
    <div>
        <a href="http://twitter.com/thierrykoblentz">
            <img src="thierry.jpg" alt="me" width="40" />
        </a>
        <div>
            @thierrykoblentz 14 minutes ago
        </div>
    </div>
</div>

CSS

Again, we create an extra rule, this time using a descendant selector, #rightRail .bd.

.media {
    margin: 10px;
}
.media,
.bd {
    overflow: hidden;
    _overflow: visible;
    zoom: 1;
}
.media .img {
    float: left;
    margin-right: 10px;
}
.media .img img {
    display: block;
}
.media .imgExt {
    float: right;
    margin-left: 10px;
}
#rightRail .bd {
    font-size: smaller;
}

RESULT

Here is our original module, showing inside div#rightRail:


me
 

@thierrykoblentz 14 minutes ago

 

 

What’s Wrong With This Model?

  • Simple changes to the style of our module have resulted in new rules in the style sheet.
    There must be a way to style things without always having to write more CSS rules.
  • We are grouping selectors for common styles (.media,.bd {}).
    Grouping selectors, rather than using a class associated with these styles, will lead to more CSS.
  • Of our six rules, four are context-based.
    Rules that are context-specific are hard to maintain. Styles related to such rules are not very reusable.
  • RTL and LTR interfaces become complicated.
    To change direction, we’d need to overwrite some of our styles (i.e. write morerules). For example:
.rtl .media .img {
    margin-right: auto; /* reset */
    float: right;
    margin-left: 10px;
}
.rtl .media .imgExt {
    margin-left: auto; /* reset */
    float: left;
    margin-right: 10px;
}

 

Meet Atomic Cascading Style Sheet

a·tom·ic
/ə’tämik/
of or forming a single irreducible unit or component in a larger system.

As we all know, the smaller the unit, the more reusable it is.

“Treat code like Lego. Break code into the smallest little blocks possible.” —@csswizardry (via @stubbornella#btconf

— Smashing Magazine (@smashingmag) May 27, 2013

To break down styles into irreducible units, we can map classes to a single style, rather than many. This will result in a more granular palette of rules, which in turn improves reusability.

Let’s revisit the media object using this new approach.

MARKUP

We are using five classes, none of which are related to content:

<div>
    <a href="http://twitter.com/thierrykoblentz">
        <img src="thierry.jpg" alt="me" width="40" />
    </a>
    <div>
        @thierrykoblentz 14 minutes ago
    </div>
</div>

CSS

Each class is associated with one particular style. For the most part, this means we have one declaration per rule.

.Bfc {
    overflow: hidden;
    zoom: 1;
}
.M-10 {
    margin: 10px;
}
.Fl-start {
    float: left;
}
.Mend-10 {
    margin-right: 10px;
}
.Fz-s {
    font-size: smaller;
}

RESULT


me
 

@thierrykoblentz 14 minutes ago

 

WHAT IS THIS ABOUT?

Let’s ignore the class names for now and focus on what this does (or does not):

  • No contextual styling
    We do not use contextual or descendant selectors, which means that our style sheet has no dead weight.
  • Directions (left and right) are “abstracted.”
    Rather than overwriting styles, we serve a RTL style sheet that contains rules such as these:
.Fl-start {
    float: right;
}
.Mend-10 {
    margin-left: 10px;
}

Same classes, same properties, different values.

But the most important thing to notice here is that we are styling via markup. We have changed the context in which we style our modules. We are now editing HTML templates instead of style sheets.

I believe that this approach is a game-changer because it narrows the scope dramatically. We are styling not in the global scope (the style sheet), but at the module and block level. We can change the style of a module without worrying about breaking something else on the page. And we can do this without adding any rule to the style sheet, let alone creating a new class and rule:

.someBasicStyleForThisElementHere {...}

We get no redundancy. Selectors are not duplicated, and styles belong to a single rule instead of being part of many. For example, the style sheets that this page links to contain 72 float declarations.

Also, abandoning a style — for example, deciding to always keep the image on the left side of the module — does not make any of our rules obsolete.

SOUND GOOD?

Not sold yet? I hear you saying, “This goes against every single rule in the book. This is no better than inline styling. And your class names are not only cryptic, but unsemantic, too!”

Fair enough. Let’s address these concerns.

REGARDING UNSEMANTIC CLASS NAMES

If you check the W3C’s “Tips for Webmasters,” where it says “Good names don’t change,” you’ll see that the argument is about maintenance, not semantics per se. All it says is that changing styles is easier in a CSS file than in multiple HTML files. .border4pxwould be a bad name only if changing the style of an element required us to change the declaration that that class name is associated with. In other words:

.border4px {border-width:2px;}

REGARDING CRYPTIC CLASS NAMES

For the most part, these class names follow the syntax of Zen Coding — see the “Zen Coding Cheat Sheet” (PDF) — now renamed Emmet. In other words, they are simple abbreviations.

There are exceptions for styles associated with direction (left and right) and styles that involve a combination of declarations. For example, Bfc stands for “block-formatting context.”

REGARDING MIMICKING INLINE STYLES

Hopefully, the diagram below clears things up:

Venn diagram that shows all possible logical relations between inline styles and styling via classes and markup.
Inline styles versus Atomic CSS.

  • Specificity
    The technique is not as specific as @style. It lowers style weight because rules rely on a single class, as opposed to rules like .parent .bd {}, which clocks in at 0.0.2.0 (see “CSS Specificity: Things You Should Know”).
  • Verbosity
    Most classes are abbreviations of declarations (for example, M-10 versus margin: 10px). Some classes, such as Bfc, refer to more than one style (see “Mapping” in the diagram above). Other classes use “start” and “end” keywords, rather than left and right values (see “Abstraction” in the diagram above).

Here are the advantages of @style:

  • Scope
    Styles are “sandboxed” to the nodes they are attached to.
  • Portability
    Because the styles are “encapsulated,” you can move modules around without losing their styles. Of course, we still need the style sheet; however, because we are making context irrelevant, modules can live anywhere on a page, website or even network.

The Path To Bloat

Because the styles of our module are tied only to presentational class names, they can be anything we want them to be. For example, if we need to create a simple two-column layout, all we need to do is replace the link with a div in our template. That would look like this:

<div>
    <div>
        column 1
    </div>
    <div>
        column 2
    </div>
</div>

And we would need only one extra rule in the style sheet:

.Bfc {
    overflow: hidden;
    zoom: 1;
}
.M-10 {
    margin: 10px;
}
.Fl-start {
    float: left;
}
.Mend-10 {
    margin-right: 10px;
}
.Fz-s {
    font-size: smaller;
}
.W-50 {
    width: 50%;
}

Compare this to the traditional way:

<div>
    <div>
        column 1
    </div>
    <div>
        sidebar
    </div>
</div>

This would require us to create three new classes, to add an extra rule and to group selectors.

.wrapper,
.content,
.media,
.bd {
    overflow: hidden;
    _overflow: visible;
    zoom: 1;
}
.sidebar {
    width: 50%;
}
.sidebar,
.media .img {
    float: left;
    margin-right: 10px;
}
.media .img img {
    display: block;
}

I think the code above pretty well demonstrates the price we pay for following the SoC principle. In my experience, all it does is grow style sheets.

Moreover, the larger the files, the more complex the rules and selectors become. And then no one would dare edit the existing rules:

  • We leave alone rules that we suspect to be obsolete for fear of breaking something.
  • We create new rules, rather than modify existing ones, because we are not sure the latter is 100% safe.

In other words, we make things worse because we can get away with bloat.

Nowadays, people are accustomed to very large style sheets, and many authors think they come with the territory. Rather than fighting bloat, they use tools (i.e. preprocessors) to help them deal with it. Chris Eppstein tells us:

“LinkedIn has over 1,100 Sass files (230k lines of SCSS) and over 90 web developers writing Sass every day.”

CSS BLOAT VS. HTML BLOAT

Let’s face it: the data has to live somewhere. Consider these two blocks:

<div>
<div>

In many cases, the “semantic” class name makes up more bytes than the presentational class name (.wrapper versus .Bfc). But I do not think this is a real concern compared to what most apps onboard these days via data- attributes.

This is where gzip comes into play, because the high redundancy in class names across a document would achieve better compression. And the same is true of style sheets, in which we have many redundant sequences:

.M-1 {margin: 1px;}
.M-2 {margin: 2px;}
.M-4 {margin: 4px;}
.M-6 {margin: 6px;}
.M-8 {margin: 8px;}
etc.

Caching

Presentational rules do not change. Style sheets made from such rules mature into tool sets in which authors can find everything they need. By their nature, they stop growing and become immutable, and immutable is cache-friendly.

No More .button Class?

The technique I’m discussing here is not about banning “semantic” class names or rules that group many declarations. The idea is to reevaluate the benefits of the common approach, rather than adopting it as the de facto technique for styling Web pages. In other words, we are restricting the “component” approach to the few cases in which it makes the most sense.

For example, you may find the following rules in our style sheets, rules that set styles for which we do not create simple classes or rules that ensure cross-browser support.

.button {
    display: inline-block;
    *display: inline;
    zoom: 1;
    font-size: bold 16px/2em Arial;
   	height: 2em;
   	box-shadow: inset 1px 1px 2px 0px #fff;
   	background: -webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ededed), color-stop(1, #dfdfdf));
   	background: linear-gradient(center top, #ededed 5%, #dfdfdf 100%);
   	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#dfdfdf');
   	background-color: #ededed;
    color: #777;
    text-decoration: none;
   	text-align: center;
   	text-shadow: 1px 1px 2px #ffffff;
   	border-radius: 4px;
   	border: 2px solid #dcdcdc;
}
.modal {
    position: fixed;
    top: 50%;
    left: 50%;
    -webkit-transform: translate(-50%,-50%);
    -ms-transform: translate(-50%,-50%);
    transform: translate(-50%,-50%);
    *width: 600px;
    *margin-left: -300px;
    *top: 50px;
}
@media screen {
    .modal {
        width: 600px;
        margin-left: -300px;
        top: 50px;
    }
}

On the other hand, you would not see rules like the ones below (i.e. styles bound to particular modules), because we prefer to apply these same styles using multiple classes: one for font size, one for color, one for floats, etc.

.news-module {
    font-size: 14px;
    color: #555;
    float: left;
    width: 50%;
    padding: 10px;
    margin-right: 10px;
}
.testimonial {
    font-size: 16px;
    font-style: italic;
    color: #222;
    padding: 10px;
}

Do We Include Every Possible Style In Our Style Sheet?

The idea is to have a pool of rules that authors can choose from to style anything they want. Styles that are common enough across a website would become part of the style sheet. If a style is too specific, then we’d rely on @style (the style attribute). In other words, we’d prefer to pollute the markup rather than the style sheet. The primary goal is to create a sheet made of rules that address various design patterns, from a basic rule that floats an element to “helper” classes.

/**
 * one liner with ellipsis
 * 1. we inherit hyphens:auto from body, which would break "Ell" in table cells
 */
.Ell {
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    -webkit-hyphens: none; /* 1 */
    -ms-hyphens: none;
    -o-hyphens: none;
    hyphens: none;
}
/**
 * kinda line-clamp
 * two lines according to default font-size and line-height
 */
.LineClamp {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    font-size: 13px;
    line-height: 1.25;
    max-height: 32px;
    _height: 32px;
    overflow: hidden;
}
/**
 * reveals an hidden element on :hover or :focus
 * visibility can be forced by applying the class "RevealNested-on"
 * IE8+
 */
:root .NestedHidden {
    opacity: 0;
}
:root .NestedHidden:focus,
:root .RevealNested:hover .NestedHidden,
:root .RevealNested-on .NestedHidden {
    opacity: 1;
}

How Does This Scale?

We have just released a brand new My Yahoo, which relies heavily on this technique. This is how it compares to a few other Yahoo products (after gzip’ing):

CSS Assets
answers.yahoo.com 30.1 KB
sports.yahoo.com 67.4 KB
omg.yahoo.com 46.2 KB
yahoo.com 45.9 KB
my.yahoo.com 21.3 KB

Our style sheet weighs 17.9 KB (about 3 KB of which are property-specific), and it is shareable (unlike the style sheets of other properties). The reason for this is that none of the rules it contains relate to content.

Wrapping Up

Because presentational class names have always been deemed “out of bounds,” we — the community — have not really investigated what their use entails. In fact, in the name of best practice, we’ve dismissed every opportunity to explore their potential benefits.

Here at Yahoo, @renatoiwa@StevenRCarlson and I are developing projects with this new CSS architecture. The code appears to be predictable, reusable, maintainable and scalable. These are the results we’ve experienced so far:

  • Less bloat
    We can build entire modules without adding a single line to the style sheets.
  • Faster development
    Styles are driven by classes that are not related to content, so we can copy and paste existing modules to get started.
  • RTL interface for free
    Using start and end keywords makes a lot of sense. It saves us from having to write extra rules for RTL context.
  • Better caching
    A huge chunk of CSS can be shared across products and properties.
  • Very little maintenance (on the CSS side)
    Only a small set of rules are meant to change over time.
  • Less abstraction
    There is no need to look for rules in a style sheet to figure out the styling of a template. It’s all in the markup.
  • Third-party development
    A third party can hand us a template without having to attach a style sheet (or astyle block) to it. No custom rules from third parties means no risk of breakage due to rules that have not been properly namespaced.

(Note that if maintenance is easier on the CSS side than on the HTML side, then the reason is simply that we can cheat on the CSS side by not cleaning up rules. But if we were required to keep things lean and clean, then the pain would be the same.)

FINAL NOTE

I was at a meetup a couple of weeks ago, where I heard Colt McAnlis say, “Tools, not rules.” A quick search for this idiom returned this:

“We all need to be open to new learnings, new approaches, new best practices and we need to be able to share them.”

(al, ea)

/**
* custom styles for this article
* Namespace: “Atomiccss”
*/
.Atomiccss .media {
margin: 10px;
}
.Atomiccss .media,
.Atomiccss .bd {
overflow: hidden;
_overflow: visible;
zoom: 1;
}
.Atomiccss .media .img {
float: left;
margin-right: 10px;
}
.Atomiccss .media .img img {
display: block;
}
.Atomiccss .media .imgExt {
float: right;
margin-left: 10px;
}
.Atomiccss #rightRail .bd {
font-size: smaller;
}
/* ACSS */
.Atomiccss .Bfc {
overflow: hidden;
zoom: 1;
}
.Atomiccss .M-10 {
margin: 10px;
}
.Atomiccss .Fl-start {
float: left;
}
.Atomiccss .Mend-10 {
margin-right: 10px;
}
.Atomiccss .Fz-s {
font-size: smaller;
}
/* for some reason, @width is stripped from the markup */
.Atomiccss img {
width: 40px;
}