Unsexy CSS3: Getting Work Done Faster

Unsexy? I’m talking about new options in CSS3 that aren’t discussed as often as their flashier brethren, like border-radius, border-image, animations, and 3d transforms. The properties below are just those kinds of items. Unsung additions that will help you get work done faster.

Granted, many of these properties aren’t available in every browser. But for those who have a high percentage of the latest browsers, are developing for advanced mobile phones, or another advanced browser monoculture, these items are available now. For those with a broader support matrix, these might serve as an excellent starting point for progressive enhancement as your browser stats improve.

These are all items that I was able to test while developing an Adobe Air 1.5 front-end for Comcast.net’s internal CMS project. I’ve also been able to use some of these features on the comcast.net iPhone and Android targeted mobile web site. A few of these saved me a couple hours of refactoring while others saved a lot of time by not having to create a traditional work-around.

OK. Let’s actually look at some code.

Box Sizing

box-sizing:(content-box | border-box);

Taking the options in order, content-box is an explicit statement that maps to the W3C box model and it’s use of width. For an element with box-sizing:content-box;, width values will refer to the width of the content. Padding and borders will add to the width value. border-box, however, is the game changer. This specifies that width will be the maximum width of the total visual element: borders, padding, and content. Content width will adjust to accommodate borders and padding. For you old timers and kids who tread in dangerous waters it’s the table cell box model. I have a feeling this one could become divisive if abused, but used sparingly, it can be very handy.

Dan Cederholm recently tweeted about using it in conjunction with floating primary grid elements.

@simplebits Man. box-sizing: border-box; + fluid layout = a match made in lean markup heaven. Ladies.
6:04 PM Apr 5th via Twitter for Mac

My example comes from a dilemma about adding a new input width to our CMS front-end. I’d already established a few primary sizes and a new smaller size was required along with error states for empty or incorrect field values that required alternate padding. I’d have to add the new size and refactor all of the existing sizes. I was not looking forward to it. Using box-sizing meant that I added box-sizing:border-box; to the base styling of all inputs, removed padding and border declarations from individual input instances and moved them to the base input, and created the error state class with alternate padding that would clear text past the inline icon.

Flex Box/Flexible Box

display:box;*
box-orient:(horizontal | vertical | inline-axis | block-axis | inherit);*
box-flex:(integer);*
box-pack:(start | end | center | justify);
box-align:(start | end | center | baseline | stretch);*
box-ordinal-group:(integer);
box-flex-group:(integer);
box-lines:(single | multiple);

Instead of worrying about the box model, wouldn’t it be great to have a way to say, “these elements should sit next to each other?” That’s what flex gives you.

Set display:box; and box-orient:val; on the parent element. Then in each stacked item add box-flex:integer; to specify the proportion of the total width each box should occupy. If all boxes should be equal width, use box-flex:1. If one box should be twice as large as the others, set equal elements to box-flex:1; and the wider element to box-flex:2. You can also enter specific widths for one box-flex value and let the other remain proportional. This is similar to how frames would allow you to specify a width and allow the remainder to expand (possibly the only thing worth saving from frames).

There are some quirks depending upon the browser implementation, so definitely check out the articles below. One thing I’ve seen in only a single article title is that you get equal height columns for free with display:box; and box-orient:horizontal.

In our CMS, I used this to create tabs to switch between direct input and selecting feed content. It was a pretty simple use, but even then I didn’t have to calculate width, padding, and borders to setup a float.

Multiple Backgrounds

Multiple backgrounds have gotten a little love since I first thought of this article. It’s still time to use it in more places, as it’s pretty well supported in more recent browsers. This one is pretty straightforward in that you can simply add another background declaration separated by a comma.

background:url(../images/icons/error.png) no-repeat 4px 4px, url(../images/icons/selectArrow.gif) no-repeat 2px right;

I found this one through the error states that I mentioned in the section on box-sizing. I’d restyled the native appearance of select menus and I was already using a background image for the arrow indicator. I thought I was stuck until a coworker said, “haven’t multiple backgrounds been supported for a while?” I found a syntax example online and the image was in and working within 10 minutes.

Selectors

Nth-Child and Nth-of-type

:nth-child()
:nth-of-type()

nth-child and nth-of-type are great selector tools for accessing specific elements or to set up repeating patterns without having to add extra markup. For instance, you can specify div p:nth-child(2) to get the paragraph that is the second child of a div. To get the every other paragraph, you could enter p:nth-child(2n). The formulas can get a little tricky, so I recommend reading SitePoint’s article, Understanding Nth-child Expressions.

Also, Chris Coyier at CSS Tricks has an excellent read on nth-child’s less tricky and potentially more useful cousin, nth-of-type. Nth-of-type gives you the numbered instance of an element, much like nth-child, but without taking all of an element’s siblings into account. div p:nth-child(2) will match only if the second child of the div is a paragraph. div p:nth-of-type(2) will give you the second paragraph if there are two paragraphs. Go read his article for more in depth coverage.

In our CMS front-end, we wanted to have horizontally stacked fieldsets to input lists of links. All the fields aligned horizontally, so we could save room by having left aligned labels only for the first fieldset in a row. We were able to specify special styling for every nth-child(3n+2) or nth-child(4n+2) items. This was an instance where the child nodes weren’t exactly as expected. Nth-of-type, probably would have been a cleaner way of accessing the same element.

Attributes

button[disabled], input[type='text'], #contentEditor fieldset[visible='false']

Semantic attributes are now available to apply appropriate styling. You can set an alternate, grayed-out style for disabled buttons. You can apply styling to text inputs without having to worry about spilling over into other input types. You can even use custom attributes, like data-val, to add additional semantic meaning and display utility.

The CMS took advantage of attribute selectors, especially with a variety of custom attributes. For saving content, buttons were grayed out (opacity changed) to visually represent that the buttons were inactive. We used it to hide elements we didn’t need on that page.

Direct Child

#contentEditor > fieldset > legend

Yup. In a monoculture, whole sections of CSS2 are also on the table. Direct child selectors are great in very clean HTML. As in the example above, you can add a custom styling to the top level legend without needing an ID or class to prevent bleed through into lower level legends. In our CMS, that’s exactly what we did. The top level legend displayed directly below the page title and made the first legend redundant. Looking back, legend :nth-of-type(1) also would have worked and probably would have been less code.

Notes

  1. timmcelwee posted this