Wednesday

CSS Tooltips

What is a tooltip? Essentially, it's a bit of text that when you hover over it (or sometimes click on it), additional information about that text is provided to you. Something like this:



HTML natively supports these with elements such as abbr, which will show the contents of the title attribute on hover; in this case, abbr is semantically meant to be used for abbreviations, like "Prof" for "Professor". Similarly, the acronym tag is meant for acronyms, like NASA. But, they both do the same thing, using the title attribute on hover. In fact, you can pretty much do this with any element; for example, you could add a title attribute on a div if you wanted, and on hover over that div, the browser will reveal your title's text. You can even style these if you wanted, such as defining "cursor: help", which will show a question mark on hover. I've added a couple of these as examples in my demo.


You could alternatively use a span for your tooltip, and by just including your hover content in the title attribute, it will behave similarly to the above examples. To style these, you'd just use "span[title]" as your selector, so you only style spans that have a title attribute in a tooltip like way. That being said, semantics would suggest that a span isn't really appropriate. Enter the CSS tooltip.


CSS Tooltips

The HTML

Your opinion may differ here, but to me a tooltip is very much like an anchor that has no destination (or maybe you have some that do, which we will also talk about later). So, I use the anchor tag here with a class of tooltip. Something like so:

Full tooltipHere is the text description for the tooltip.
You'll also see that I've added a span in there that contains the descriptive text I want to reveal on hover. This is the entirety of the HTML needed here. You'll notice that I'm not defining an href here, this is on purpose, because in my case this won't actually link to anything (more on this later).


The CSS

Here we go:

.tooltip {
    position: relative;
}

.tooltip span {
    display: none;
}

.tooltip span,
.tooltip span:hover {
    color: #fff;
    cursor: default;
}

.tooltip:hover span {
    display: block; 
    position: absolute; 
    top: 1.7em; 
    left: 0;
    width: 150px;
    padding: 3px;
    background: rgba(0,0,0,.85);
    border: 2px solid #000;
    border-radius: 5px;
    box-shadow: 2px 2px 5px #333;
    z-index: 9;
}

.tooltip span:before {
    content: "";
    height: 0;
    width: 0;
    border-bottom: 7px solid #000;
    border-right: 7px solid transparent;
    border-left: 7px solid transparent;    
    position: absolute;
    top: -9px;
    left: 3px;
}

a.tooltip[href]:hover {
    cursor: pointer;
}


Let's break this down...


  1. First, I want to set a position context on my .tooltip class so that I can position my span absolutely relative to the tooltip. I do that by setting "position: relative".
  2. Next, I want the default behavior for that span to be "display: none" so it doesn't show up until we want it to.
  3. The real action of this is using ".tooltip:hover span" and setting "display: block". This will reveal the contents of my span on hover over the tooltip. Of course, without some absolute positioning, it will just run inline next to our tooltip, which isn't what we want.
  4. Now we can start styling our span...I'm offsetting it to the bottom of the tooltip, giving it a semi-transparent background using RGBA (note RGBA browser support), adding a border and rounding the corners a bit, and adding a box-shadow
  5. Finally, I wanted to add a little arrow pointing to the tooltip as a nice touch; I accomplished this with a CSS Arrow (which I wrote a tutorial on), and positioning it absolutely just outside my span. Adding z-index finishes things off so we have the right layering...
Presto!


Full Demo With Code


Additional Stuff

I mentioned earlier that you could also use this in other ways, e.g. for an anchor for which you want to include an href. I've included a simple example of this in my demo, the only variant I chose was that anchors that have an href are underlined, indicating they are clickable (I also changed the cursor to a pointer indicating clickable); You can style these however you want. In fact, using attribute selection, you could add a nice little icon next to (probably after) your link as further indication to the user what kind of interaction they can expect. Taking that just a step further, you can use attribute/value selection to target anchors that define the link to be opened in a new window (i.e. target="_blank"), or select anchors that contain the string "http" to indicate an external link (instead of a relative link to your own site, e.g. /foo.html). Anyhow - lots of fun to be had here. Enjoy!

Thursday

CSS Zebra Striping

We used to do this with either javascript (by adding and removing class names to our table rows), or with html (by adding class names to alternating rows), but CSS3 now let's us do this really easily. Here's my example:

The Code

It's pretty straight forward actually; our table here is totally typical with no added classes or markup than you would normally include. The zebra striping here comes from utilizing the following:

tr:nth-of-type(even) td {
    background: #eee;
}

What this does is for every even table row, add a light gray background to all of it's table data cells. You could easily alternate by odd rows as well:

tr:nth-of-type(odd) td {
    background: #eee;
}

There's lots of other things you can do too, like stripe every 3rd row:

tr:nth-of-type(3n) td {
    background: #eee;
}

Or stripe every 3rd row, but include the first row:

tr:nth-of-type(3n+1) td {
    background: #eee;
}

Here, I opted for the standard even row alternating zebra striping, but also added a hover just because I like that effect:

tr:hover td {
    background: #08d;            
}
Anyhow, that's all there is to it.

Full Demo with Code

Browser Support

As with most juicy CSS3 stuff, IE8 and older doesn't handle this feature (specifically the "nth" type selectors). If you really must support zebra striping for these users, you'll have to fall back to the old school way of doing so, but given the additional work involved in that for such little benefit, it seems a better idea to let those users experience your otherwise perfect table.

Wednesday

Different list item bullet and text colors

What if you have a bulleted list where you want the bullet color to be different than your text color? There's no property in the list-style that allows for this, unless you want to use images for your bullets, so instead we'll just add a span within our list items, and style the list and the list spans with different colors.


The Code

In this example, I'm adding 4 list items, the first 2 without the span, and the last 2 with so we can see the difference:

My list items with a span will look like so:

  • This one does have a span in it
  • And then, we add our CSS, selecting our spans and defining a different color than for our ul:
    ul {
        margin: 50px; 
        list-style: inside; 
        color: red;
    }
    
    ul span {
        color: black;
    }​
    
    Presto.

    Full Demo with Code

    Monday

    CSS Arrows Explained

    Overview

    CSS arrows are pretty cool and have been around a little while now. I've used them in a couple of small projects and while they save me from cutting new images for arrows, the biggest benefit I think is that they allow for super fast changes in size, color, etc, without having to re-cut new images with every design iteration. That being said, I initially found it a bit difficult to grasp HOW they worked. So, here we are...

    The basics

    First, you need an HTML element to attach your styles to. I generally think of arrows as being almost always an inline element (i.e. flows right next to (inline with) other text), as in a toggle link to show/hide content on the page or sort links, etc. As such, I like the span tag:

    
    
    I'll set a class of "arrow" on my span to use as the base setup stuff, and in this case a "right" class that I'll use to define my right arrow styling. Later on I will add classes for each arrow direction (up, down, left, right); another naming approach would be to use compass classes too if you like that (e.g. arrow-NE, arrow-S, etc).

    Base CSS

    I'm adding a margin to my .arrow class just to add some breathing room between my arrows in this example, but this part is not necessary for our arrows. The first thing I need to do is define my span size to 0. This is because we will be using BORDERS to define our arrows, and in order to keep a nice point, we need a 0x0 pixel box. Because inline elements don't have dimension like a block element does, we'll need to set our display to inline-block. As an alternative, you could use display: block, but then you would have to deal with floats and overflows and such. This allows us to define dimension on our span, but still keep it drawn inline. Of course, inline-block isn't well supported by IE7, so to help with that (or not, up to you), we could add *display: inline, and zoom: 1, which will allow IE7 to behave how we want:

    .arrow {
        margin: 5px;
        height: 0;
        width: 0;    
        display: inline-block;
        /* IE7 inline-block hack */
        *display: inline;
        zoom: 1;
    }     
    

    Adding the Arrows

    Okay, now we get to the meat of things. As I mentioned earlier, we are going to be using borders to work our magic. Most often we add a single color border to our elements, so whatever border-width we have defined, the borders are drawn as a nice thick (or thin) solid border around our box. But, what happens when we define different colors for different sides of our box? Well, something like this happens:

    Basically, the browser miters the corners together. All of a sudden, we start seeing the arrow shape we want, so from here it's really about defining just ONE of these arrows by using borders on only 3 sides of our box, and using a combination of color and transparency.

    Now let's apply this to our "right" class. Looking again above at our grayscale box with the 4 inward pointing arrows, we want to mimic the lightest gray arrow. This is achieved by defining a colored left border, and transparent top and bottom borders. The top and bottom transparent borders are working exactly as our above example's top (black) and bottom (#666 gray) borders/arrows. In my case, I wanted to use orange and have a 25px tall arrow:

    .right {
        border-left: 25px solid orange;
        border-top: 25px solid transparent;
        border-bottom: 25px solid transparent;    
    }
    

    Putting it all together

    Now we can build out our arrow variants. I'll start with adding several example spans with classes for each direction I want to represent:

    
    
    
    
    
    
    
    
    
    
    And then add in my arrow styles:
    .right {
        border-left: 25px solid orange;
        border-top: 25px solid transparent;
        border-bottom: 25px solid transparent;    
    }
    .left {
        border-right: 25px solid orange;
        border-top: 25px solid transparent;
        border-bottom: 25px solid transparent;    
    }
    .down {
        border-top: 25px solid orange;
        border-left: 25px solid transparent;
        border-right: 25px solid transparent;    
    }
    .up {
        border-bottom: 25px solid orange;
        border-left: 25px solid transparent;
        border-right: 25px solid transparent;    
    }
    .up-left {
        border-top: 25px solid red;    
        border-right: 25px solid transparent; 
    }
    .up-right {
        border-top: 25px solid red;    
        border-left: 25px solid transparent; 
    }
    .down-left {
        border-bottom: 25px solid red;        
        border-right: 25px solid transparent;
    }
    .down-right {
        border-bottom: 25px solid red;        
        border-left: 25px solid transparent;
    }
    ​And presto - now we have nicely defined classes for each of our arrows:
    

    Full Demo With Code

    Additional Stuff

    You could add a border radius if you wanted, but it would only effect the outside border edges; i.e. the "point" of the arrow will still be pointed. Still, it's a nice effect to lightly soften the outside points.

    You could also add arrow tails by using :before on your arrow classes, adding content: "", giving it some dimension and color and position relative to your .arrow class (which you'd add a position: relative to set positioning context), etc...Additionally for the angled arrows (e.g. up-left, down-right), you could use CSS rotation with a 45deg (or -45deg) angles.

    Finally, you could consider adding some animated rotation to your arrow direction. For example, you may have a right pointed arrow indicating an openable drawer of content, and onClick, you could add/remove your direction class to point the arrow down and animate between them. I haven't played with this yet, but it could be pretty sweet. Hooray CSS!

    Tuesday

    CSS Flag Banners


    I'm not sure if that's what these things are called, but that's what I'm calling this thing:

    Whatever we call it, I did it using only CSS, and thought I'd show how I did so.

    Code

    Really, it's pretty straight forward; I'm using the :before selector to my element (in this case .date-outer), to add some blank content. I need it to have dimension, so I'll add display: block, and because I want a height of 40px, I'll add that, with a width of 0 (more on that in a minute):

    .date-outer:before {
     content: "";
     display: block;
     height: 40px;
     width: 0;
    }
    

    I'm going to absolutely position this thing, but because I need to set the position context to the .date-outer element, I'll add position: relative to it:

    .date-outer {
     position: relative;
    }
    

    And then define my position for my flag thingy with a top offset of 0 (it will snap to the top of .date-outer), and a negative left offset so it'll hang off the left side (my -17px left offset places the flag hanging sort of half way off the left of my element):

    .date-outer:before {
     content: "";
     display: block;
     height: 40px;
     width: 0;
     position: absolute;
     top: 0;
     left: -17px;
    }
    

    Now, I'll define my flag with borders. First I'll add a left border of black, and a right border of red, both of 15px. This would just make a 2 color rectangle on it's own, but by adding a transparent border-bottom of 15px as well, I get a nice upward facing transparent arrow notched out of the bottom of my rectangle. Then, I just added a border radius to round out the top-left of the flag, and presto:

    .date-outer {
     position: relative;
    }
    .date-outer:before {
     content: "";
     display: block;
     height: 40px;
     width: 0;
     position: absolute;
     top: 0;
     left: -17px;
     border-top-left-radius: 15px;
     border-left: 15px solid #000;
     border-right: 15px solid red;
     border-bottom: 15px solid transparent;
    }
    

    A tiny step further

    For fun, I wanted to alter the color of my flag for each of 3 posts on the main page. I accomplish this by utilizing nth-of-type, and for my 2nd and 3rd :before styles, I'll define my left border color as a dark gray and a lighter gray (respectively):

    .date-outer:nth-of-type(2):before {
     border-left-color: #666;
    }
    .date-outer:nth-of-type(3):before {
     border-left-color: #999;
    }
    

    Support

    This latter bit isn't supported by IE8 and older, but otherwise it's pretty safe to use.

    Monday

    Lists cannot be children of Paragraphs

    Yes, truly. I admit I was a little surprised at learning this, but according to the W3 HTML spec for the p element:

    List elements (in particular, ol and ul elements) cannot be children of p elements.
    Reading a bit further, paragraphs are intended for phrasing content:
    Phrasing content is the text of the document, as well as elements that mark up that text at the intra-paragraph level.
    Also,
    Most elements that are categorized as phrasing content can only contain elements that are themselves categorized as phrasing content, not any flow content.
    Whereas, lists (e.g. ul, ol) are defined as flow content.

    Impact

    What happens when you have a list as a child of a paragraph? It turns out that the browser will actually close your p tag when it tries to render your list. It does this at the start of your list. In my example, I show a paragraph with a ul inside it, and attempt to select the ul to color it blue. But it doesn't work due to the above (per the specification, properly rendered) behavior.

    DEMO WITH CODE

    Learn something new every day. :-)

    Sunday

    Twitter Bootstrap Nested Nav Lists

    Overview

    I finally was able to begin using Twitter Bootstrap in a recent project for which I am recreating a complex navigation into the new Bootstrap interface. But, I found that while I needed to support nested nav lists within the top level nav list, Bootstrap doesn't seem to have any built in support for it: Bootstrap Navbar.

    So, I built support for it; and here's what I came up with:
    (screenshot)



    The Code

    I wanted to preserve Bootstrap's naming convention and HTML structure, so I didn't want to do anything really very new. I also wanted to retain their common styling, but come up with something that worked for sub navigation. So, I started with adding my HTML
    (forgive the html styling here, the tool I'm using doesn't prettify very well):

    So, basically I just repeated their existing convention, and added a "nav nav-list" classed li, with a dropdown-menu ul under it.

    Next, I needed to start styling; using their common style, I enhanced the nexted nav functionality by adding :hover state show/hide of the sub menu list.

    .nav li.dropdown ul.dropdown-menu li:hover ul {
        display:block;
        position:absolute;
        left:100%;
        -webkit-border-radius: 3px;
        -moz-border-radius: 3px;
        border-radius: 3px;
    }
    
    .nav li.dropdown ul.dropdown-menu ul {
        display: none;
        float:right;
        position: relative;
        top: auto;
        margin-top: -27px;
    }
    
    Bootstrap on it's own adds carets (the arrows) for dropdown menus, and sort of assumes the sub-nav will always be below your menu item. So the menu item's caret/arrow always pointed down, and the sub-nav's menu arrow always pointed up; I needed to address this:
    .nav li.dropdown ul.dropdown-menu .nav-list .caret {
        border-bottom-color: #999;
        border-top-color: #999;
        float: right;
    }
    
    .nav li.dropdown ul.dropdown-menu .nav-list:hover .caret {
        margin-left: 6px;
        margin-top: 5px;
        margin-right: 1px;
        border-right: 0;
        border-left: 4px solid #fff;
        border-top: 4px solid transparent;
        border-bottom: 4px solid transparent;
    }
    
    .nav li.dropdown ul .nav-list .dropdown-menu:after {
        top: 8px;
        left: -12px;
        border-top: 6px solid transparent;
        border-bottom: 6px solid transparent;
        border-right: 6px solid #fff;
    }
    
    .nav li.dropdown ul .nav-list .dropdown-menu:before {
        left: -7px;
        border-left: 0;
        top: 7px;
        border-top: 7px solid transparent;
        border-bottom: 7px solid transparent;
        border-right: 7px solid rgba(0,0,0,0.05);
    }​
    
    Here things began to get a little tricky; specifically, Bootstrap uses CSS borders to draw their carets/arrows (which I think is a great approach by the way); this is fine, but because I'm inheriting their styles on my new nav element, I needed to reverse the borders I didn't want so I could adjust the direction of my caret/arrow to the right and left (for the sub nav); then I could add the styles I did need, with colors appropriate for my nesting.

    Finally, I added in some common list item over styling:

    .nav li.dropdown ul.dropdown-menu li.nav-list:hover {
        background: #08c;
        color: #fff;
        cursor: pointer;    
    }
    
    .nav li.dropdown ul.dropdown-menu .nav-list {
        font-size: 13px;
        color: #333;
        float: none;
        line-height: 21px;
    }
    

    FULL DEMO WITH CODE

    Add here you have the finished product...we now have a dropdown menu list, with sub-nav elements, indicated by custom carets, when hovered reveal their own dropdown lists (though dropped to the right), with left arrows instead of up arrows, and all commonly styled ala Bootstrap. Boo yah!