CSS: differences between visibility:hidden and display:none

People who start studying CSS sometimes get confused by the subtle differences between properties that apparently seem to be similar. This is the case of display: none and visibility: hidden. To properly understand these differences, we have to bear in mind some simple concepts.

First of all, these two properties work on different levels. While the former handles the actual visual rendering of elements, the latter simply adjusts their visibility. So if you use display: none, an element is not displayed at all, that is, it has no impact on the rendering of the page. On the contrary, if you use visibility: hidden, an element is simply hidden but still has an impact on the rendering, for example by occupying a certain amount of space.

Bear in mind, however, that both declarations pose some accessibility problems. In fact, most screen readers won't read aloud the content of an element if such element has one of these declarations applied on it. My advice is to use these declarations only on elements that are not important for a proper use/understanding of your documents (for example hr elements).

CSS: styling form elements

Styling form elements with CSS can actually be a little bit tricky if we don't understand how these elements work. First of all, the overwhelming majority of form controls are inline-block elements. This set includes text fields, radio and checkbox buttons, the select element and the textarea element. Another thing to bear in mind is that the overall dimensions of one of these form controls are actually determined by the font in use on such elements (including family and size).

Now let's start with a basic blog form for posting comments, like this:

<form action="" method="post">

<ul>

  <li>
  
      <label for="name">Name</label>
      <input type="text" name="name" id="name" />
  
  </li>
  
  <li>
  
      <label for="email">E-mail</label>
      <input type="text" name="email" id="email" />
  
  </li>
  
  <li>
  
      <label for="website">Website</label>
      <input type="text" name="website" id="website" />
  
  </li>
  
  
  <li>
  
      <label for="comment">Comment</label>
      <textarea name="comment" id="comment" cols="15" rows="20"></textarea>
  
  </li>



  

</ul>

<p><input type="submit" name="submit" id="submit" value="Send" /></p>

</form>

Note that we're using an unordered list to group our form elements. This makes a lot easier to use simple selectors and cascade, as shown below:

form {

    margin: 0;
    height: 100%;
    padding: 0.5em;
    border: 1px solid #999;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    font-size: 1.3em;

}


form ul {

    margin: 0;
    padding: 0.3em;
    list-style: none;
    height: 100%;
    background: #eee;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;


}

form ul li {

    height: 100%;
    padding-bottom: 0.5em;
    overflow: hidden;

}

form ul li label {

    float: left;
    display: block;
    width: 5em;
    padding-right: 0.5em;
    font-weight: bold;

}

form ul li input {

    float: left;
    display: block;
    width: 140px;
    border: 1px solid #cbcbbb;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    background: #fff;
    font: 1em Arial, Helvetica, sans-serif;
}

form ul li textarea {

    float: left;
    width: 300px;
    height: 250px;
    display: block;
    border: 1px solid #cbcbbb;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    background: #fff;
    font: 1em Arial, Helvetica, sans-serif;
    overflow: auto;
    

}

form p {

    padding: 0.5em 0;
    margin: 0;

}

form p input {

    background: #999;
    font-weight: bold;
    color: #fff;
    border: 1px solid #cbcbbb;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;

}

The only thing to note here is the fact that we've specified a font on the input and textarea elements, except for the submit button. Note also how this element looks smaller than the others. You can see the final result below.

CSS: managing import rules

The at-rule @import is used by CSS to import the content of a style sheet into another. This kind of rule must appear at the beginning of your CSS file, like so:

@import "external.css";

/* Other style rules */

The first problem that you may encounter with imported CSS is due to cascade: if you have subsequent conflicting rules in your main CSS file, then these rules will win over those used in your imported one because of the fact that both style sheets are parsed as a unique CSS file, so the rules of your main file will come later in source.

Another problem that you may encounter is merging imported style sheets with a server-side language. For example, in a past project I used the following approach:

@import "base.css";
@import "layout.css";
@import "typography.css";
@import "colors.css";

The server-side developer (who used Ruby) encountered several problems when trying to merge these files properly and in the correct order, due to some issues with his Ruby version. Anyway, be aware of this fact.

The most relevant problem with this approach is, above all, performance. If you take the above example, a browser must execute five GET requests, one for the main file and four for the imported style sheets. If your site is a small blog or a content-centric web site, then you won't probably notice the difference. On the contrary, if you're working on a complex web application or on a huge Web 2.0 web site, then you'll probably see noticeable delays in the rendering of your web pages.

I'm not saying that you should not use these rules. Far from it. I'm only saying that, like for other CSS features, you should always take the pros and cons into account before writing your code.

FBML and HTML validation

FBML (FaceBook Markup Language) is a markup language proposed by Facebook to extend some of the core functionalities of the social network itself. In its simplest form, it's made up of code snippets that, once inserted into the markup of a web document, allow us to use some Facebook's gadgets and widgets.

For example, the following code adds a "Like" button to our pages:

<fb:like href="http://www.site.com/"></fb:like>

Unfortunately, this code won't pass the W3C validation. Theoretically speaking, this problem would arise only with HTML, which is not extensible and its DTD is immutable. On the contrary, if we serve our documents as XHTML 1.1 and with a custom DTD, then we could use FBML without any problem.

I say "theoretically", because with XHTML 1.1 we must:

  1. serve our documents as application/xhtml+xml
  2. specify the FBML namespace in the root element (html)
  3. create a custom DTD

However, none of these steps can actually be done without a firm knowledge of how XML works, plus a long practice with parsing, DTDs, namespaces and XHTML 1.1. Is there a solution? Yes, and it involves injecting the above snippet directly into the DOM via JavaScript. For example, by using jQuery:

var $fbLike = '<fb:like href="http://www.site.com/"></fb:like>';
$($fbLike).appendTo('body');

But now a major accessibility problem arises: we have to deal with browsers that don't support JavaScript or have JavaScript turned off. Then we must provide the following fallback mechanism:

<noscript>
       <p><a href="http://www.facebook.com/plugins/like.php?href=http%253A%252F%252Fwww.site.com">Like</a></p>
</noscript>

By providing a simple textual link within a noscript tag we cater the accessibility needs of our users.

CSS: how opposite floats work

As web developers, we're usually accustomed to use CSS floats only in simple ways in order to build our layouts. Sometimes, however, floats get more complicated especially when we use a combination of left and right values.

To start our little journey inside opposite floats, let's draw a simple HTML skeleton:

<div id="container">

<div class="row">

<div class="alignleft"></div>
<div class="alignright"></div>

</div>

<div class="row">

<div class="alignleft"></div>
<div class="alignleft"></div>
<div class="alignleft"></div>
<div class="alignright"></div>
<div class="alignright"></div>
<div class="alignright"></div>


</div>


<div class="row">

<div class="alignleft"></div>
<div class="alignright"></div>
<div class="alignleft"></div>
<div class="alignright"></div>
<div class="alignleft"></div>
<div class="alignright"></div>


</div>


<div class="row">

<div class="alignleft"></div>
<div class="alignright"></div>
<div class="alignright"></div>
<div class="alignleft"></div>
<div class="alignright"></div>
<div class="alignright"></div>


</div>

<div class="row">

<div class="alignright"></div>
<div class="alignleft"></div>
<div class="alignright"></div>
<div class="alignleft"></div>
<div class="alignright"></div>
<div class="alignleft"></div>


</div>

</div>

with really basic styles:

#container {

    width: 600px;
    margin: 0 auto;

}

div.row {

    height: 100%;
    overflow: auto;
    padding-bottom: 1em;
    

}

div.alignleft {

    float: left;
    width: 100px;
    height: 100px;
    background: green;

}

div.alignright {

    float: right;
    width: 100px;
    height: 100px;
    background: orange;

}

We have a container with five rows of floated elements. More precisely, we're taking into account some possible combinations of left-floated and right-floated elements (from two up to six). So we have:

  1. First row: left-right
  2. Second row: left-left-left-right-right-right
  3. Third row: left-right-left-right-left-right
  4. Fourth row: left-right-right-left-right-right
  5. Fifth row: right-left-right-left-right-left

You can see the results in the following picture.

As you can see, in some cases result differs from what we did expect (the only noticeable change is in the 4th row). In such cases, the best approach is testing some possible combinations of floats to make ourselves clear what it's actually happening under the hood.}

CSS: use of background images

The first thing you need to bear in mind when dealing with CSS background images is the stacking order of the images. Images are stacked according to the source code order and relationship between parent and child elements. So the background image of the outermost element always covers the background images of the innermost one.

For example, if you want to stack four rounded corners using the old-fashioned technique of the four stacked divs, you have something like this:

#box {
    background: #eee url(img/top-left.gif) no-repeat 0 0;
}

#box-top-right {
    background: url(img/top-right.gif) no-repeat 100% 0;
}

#box-bottom-left {
    background: url(img/bottom-left.gif) no-repeat 0 100%;
}

#box-bottom-right {
    background: url(img/bottom-right.gif) no-repeat 100% 100%;
}

Notice that:

  1. The background-color of the box is set on the innermost element. If you set it on another of the four elements, the background color of the outermost element will cover the background image of the innermost one.
  2. The background-position property has been set using the x and y coordinates, respectively. So '0 0' means 'top left' and '100% 100%' means 'bottom right'. You can use also keywords, but you cannot mix up keywords and lengths (that's invalid).

When creating background images with your favorite image editor, always remember to handle transparencies very carefully. If your element has a given background color and your image as a transparent portion, then the background color of the element will fill the transparent portion (and sometimes this is not what you really want).

Another thing to keep in mind is how the external boundaries of your image are rasterized. For example, if you have a tiled background image with a gradient on an innermost element and a single background image with a transparent background on an outermost one, then you need to check if these two images combine gracefully. If transparency is not handled properly, you could get some undesired effect when it comes to stack both images over each other.

Some obscure details of CSS

I've been using CSS for almost six years. During this period, sometimes I wondered about some obscure details of CSS specifications. These details are listed below.

  1. Layering and stacking order

    When elements are absolutely positioned, it's crucial to determine how they should be overlapped. The problem is that most browsers don't agree on how this stacking order should be displayed. For example, consider the following:

    #container {
      position: relative;
    }
    
    #child {
      position: absolute;
      z-index: -1;
    }
    

    In this case, this element should not be displayed, since we gave to it a negative z-index. Unfortunately, some browsers don't consider 0 as the starting value for the stacking order, so this rule won't work in some cases.

  2. Clearing and containing floats

    As developers, we all know a series of techniques for clearing and containing floats, which includes:

    • overflow:auto/hidden
    • position: absolute

    I mentioned only those that keep me wondering about how they actually work. We all know that floats make vertical space collapse. However, when the former declaration is applied to a parent element, browsers automatically expand the available vertical space to include floats, even when those floats have no stated height. So we should assume that browsers automatically calculate the height of these elements and react accordingly.

    Instead, the latter declaration is even more complicated. We just assume that the vertical space is calculated again according to the actual height of floats, but I don't think this is a sufficient explanation. CSS specifications don't say much about this issue. More precisely, they don't say much about the general problem of clearing and containing floats.

  3. Negative margins

    The question is: "How negative margins affect the computation of the overall dimensions of a containing block?" By subtracting a given length, both horizontal and vertical, what is the computed value of the width and height of a containing block? This should be further investigated.

jQuery: form validation with HTML5

HTML5 allows us to get a finer control over form elements. In fact, with the newly introduced form attributes and values we can perform more advanced validation routines using jQuery. For example, given a form like this:

<form action="" method="post">
<ul>
<li><label for="username">E-mail</label>
<input type="email" name="username" id="username" required="required" /></li>
<li><label for="password">Password</label>
<input type="password" name="password" id="password" required="required" /></li>
</li>
</ul>
</form>

we can easily check required values thanks to the required attribute:

$('input[required]').each(function() {
    var $input = $(this);
    checkRequired($input);
});

Further, we can even perform data-specific validation routines, for example on emails:

$('input[type=email]').each(function() {
    var $email = $(this);
    checkEmail($email);
});

In this case, data-specific validation is also performed by web browsers to check if a given data type is in the correct format. Here the email value must honor the rules contained in the RFC 2822 specification.

jQuery: basic animations

jQuery's animations are actually performed by the animate() method. Let's start with a simple HTML structure:

<div id="container">

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

</div>

with the following styles:

#container {

    width: 400px;
    height: 100px;

}

.left {

    background: orange;
    width: 100px;
    height: 100px;
    float: left;
    position: relative;

}

.right {

    background: yellow;
    width: 100px;
    height: 100px;
    float: right;
    position: relative;

}

We want the two floated elements exchange their position within their container. The jQuery code is really simple:

$(document).ready(function() {

    $('#animate').click(function() {
    
        $('.left').animate({left: '300px'}, 'slow');
        $('.right').animate({right: '300px'}, 'slow');
        
        return false;
    
    });

});

The offset for the animation is given by the subtraction of the overall width of the container minus the width of each box. The second parameter determines the speed of the animation (in this case is slow). Optionally the animate() method accept a callback function to be executed as the third parameter when the animation is complete. You can see the final result here.

Using CSS3 namespace selectors on a blog feed

Let's start with an XML fragment taken from a well-known blog:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="style.css" type="text/css"?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xml:base="http://annevankesteren.nl/archives/href">
 <channel rdf:about="http://annevankesteren.nl/feeds/href.rdf">
  <title>Anne’s Weblog about Markup & Style - HREF</title>
  <description>Links matter</description>
  <link>http://annevankesteren.nl/archives/href</link>
  <dc:date>2005-06-24</dc:date>
 </channel>
 <!--more-->
</rdf:RDF>

Now let's use our CSS3 namespace selectors:

@namespace RDF "http://purl.org/rss/1.0/";
@namespace dc "http://purl.org/dc/elements/1.1/";
@namespace rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#";

rdf|RDF {

    display: block;
    background: #eee;
    color: #333;
    margin: 0;
    width: 100%;
    font: 76% Arial, sans-serif;

}

channel {

    width: 60%;
    margin: 2em auto;
    padding: 1em;
    background: #fff;
    font-size: 1.2em;
    display: block; 
    border: 5px solid gray;
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;

}

channel title {

    display: block;
    font: 2em "Trebuchet MS", Trebuchet, sans-serif;
    color: #454545;
    margin-bottom: 0.2em;
    border-bottom: 4px double;
    padding-bottom: 2px;

}

channel description {

    display: block;
    padding: 5px;
    margin-top: 5px;
    font-family: Georgia, serif;
    font-style: italic;

}

channel link {

    display: block;
    margin-bottom: 0.3em;
    color: #338;
    cursor: pointer;

}

channel dc|date {

    display: block;
    font-size: small;
    margin: 0 0 0.5em 0;
    padding: 0.3em;
    background: #f5f5f5;
    border: 1px solid #cbcbbb;

} 

We've declared all the namespace used throughout the document and used the suffix selectors to match the elements we want to stylize. You can see the result below.

jQuery: the ready() event method in details

The jQuery's ready() event is related to the following DOM/jQuery's states and structures:

  • the DOMContentLoaded event
  • the document object
  • the readyList array
  • the isReady property
  • the bindReady() method
ready: function( fn ) {
  // Attach the listeners
  jQuery.bindReady();

  // If the DOM is already ready
  if ( jQuery.isReady ) {
   // Execute the function immediately
   fn.call( document, jQuery );

  // Otherwise, remember the function for later
  } else if ( readyList ) {
   // Add the function to the wait list
   readyList.push( fn );
  }

  return this;
}

Basically, this method performs two actions:

  1. if the DOM is fully loaded, it performs the function immediately
  2. otherwise, it puts that function in a queue for later use.

The handler ready() performs all the required work:

// Handle when the DOM is ready
 ready: function() {
  // Make sure that the DOM is not already loaded
  if ( !jQuery.isReady ) {
   // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
   if ( !document.body ) {
    return setTimeout( jQuery.ready, 13 );
   }

   // Remember that the DOM is ready
   jQuery.isReady = true;

   // If there are functions bound, to execute
   if ( readyList ) {
    // Execute all of them
    var fn, i = 0;
    while ( (fn = readyList[ i++ ]) ) {
     fn.call( document, jQuery );
    }

    // Reset the list of functions
    readyList = null;
   }

   // Trigger any bound ready events
   if ( jQuery.fn.triggerHandler ) {
    jQuery( document ).triggerHandler( "ready" );
   }
  }
}

This handler checks if the body element exists and in that case runs all functions in sequence by using the JavaScript call() function within a while loop that iterates over the readyList array. Finally, the bindReady() method actually binds this event to the document object:

bindReady: function() {
  if ( readyBound ) {
   return;
  }

  readyBound = true;

  // Catch cases where $(document).ready() is called after the
  // browser event has already occurred.
  if ( document.readyState === "complete" ) {
   return jQuery.ready();
  }

  // Mozilla, Opera and webkit nightlies currently support this event
  if ( document.addEventListener ) {
   // Use the handy event callback
   document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
   
   // A fallback to window.onload, that will always work
   window.addEventListener( "load", jQuery.ready, false );

  // If IE event model is used
  } else if ( document.attachEvent ) {
   // ensure firing before onload,
   // maybe late but safe also for iframes
   document.attachEvent("onreadystatechange", DOMContentLoaded);
   
   // A fallback to window.onload, that will always work
   window.attachEvent( "onload", jQuery.ready );

   // If IE and not a frame
   // continually check to see if the document is ready
   var toplevel = false;

   try {
    toplevel = window.frameElement == null;
   } catch(e) {}

   if ( document.documentElement.doScroll && toplevel ) {
    doScrollCheck();
   }
  }
 },

Here the DOMContentLoaded event is handled in a cross-browser way to make sure that also Internet Explorer will run the code sequence correctly. Anyway, the result will not be exactly the same because some versions of IE don't support the W3C DOM event at all.