Using CSS to create list-items with differently colored bullets and text

The new design for a website I’m working on calls for the ability to style bullets and the following list-item text with different colors, which isn’t an easy task for your plain-Jane CSS unless you use images for your bullets.  This is not desirable because each section of the site has a different theme color, so I’d have to create and manage bullet images for every color used.  Not to mention the extra HTTP requests which slow pages down.  But there’s a better way, and it even degrades gracefully with older browsers!

This image shows what the end result should look like.  This special bullet styling should only be applied to the user-generated content (UGC), like pages and posts.  Nav items, and other cases where <ul>‘s are used for semantic purposes, should not use this styling.

To make this happen, I added a .ugc CSS class to the container element for the post and page text, and then added the appropriate stylesheet rules to any list-item elements within.

You’ll see that I first remove list-style from all <ul>‘s within a .ugc container by setting it to “none”.  Adding the “position: relative;” style to the <li>‘s allows for me to use it as an origin for some absolute positioning with other elements.  The trick to using different colors with bullets and text is to create pseudo-elements for the bullets using the “:before” pseudo-selector.  The .ugc li:before selector shown above defines a new element created right from CSS, absolutely positioned from the <li> element, with a width and height of 5px, a purple background and a border radius relative to the size so as to make the element appear circular.  Cool, huh?

(Note:  Ignore the “@purple” color and what looks like incorrect border-radius syntax, this is LESS syntax which gets compiled correctly to the correct CSS, including browser-specific prefixes.)

You’ll also see some fallback code for IE browsers before IE8, which is fairly self-explanatory.  I conditionally add CSS classes to IE browsers a la Paul Irish’s elegant solution, and so older, crappy browsers can also enjoy the separately colored bullets.

Of course, I realized that those cool styles apply to all of the targeted list-item elements within my user-generated content, and sometimes they shouldn’t.  If you drop some extra page navigation within the element having the .ugc class, or perhaps paste a code snippet to show off your own cool coding tricks, you’ll need to remove your cool bullets.  For example, if I have some Twitter Bootstrap tabs that get mixed up with my content via a WordPress shortcode or something, here’s how I’d remove the bullets that will show up (and not be easy to track down with Firebug):

Just use those same :before pseudo-selectors and set their display property to “none”.  Done and done!

Hey Designers, Tweak All You Like. Developers Have Sass and Compass.

Developers can all relate to a fast-approaching deadline, and though your plate is already full, your email dings at you and you’re faced with yet another request from the designer you’re working with to change the look and feel of your project.  Swap that background image, add some margin, adjust the kerning, maybe un-serif all of the fonts – but those CSS properties are used across an unfathomable number of UI elements throughout your entire website with 5 different page templates!  I say bring it, and I’m going to show you exactly why.  Keep reading to get the full picture, or skip directly to the code if you’re feeling antsy.

Sass is the next evolution of stylesheets, which allows the use of variables, functions, reusable chunks called mixins, and other cool features that CSS has been missing.  Compass is a related framework that adds functionality and makes working with Sass a little easier.

Designers and developers alike will certainly appreciate how integrating Sass and Compass into your development workflow can make these tweaks as smooth and painless as possible by allowing you to update a style in one place, and have it propagate to all of the CSS rules where that style is used.

Where Designers are Coming From

Look, it’s our job to support designers.  Not because we’re their “code monkeys” – instead, we’re both trying to achieve the same lofty goals our new project has encouraged us to set for ourselves, and that means we need to improve our flexibility to accommodate any design changes as best we can just as they must do.  Designers aren’t making changes to core interface elements because they want to rob us of our time spent catching up on last night’s Jon Stewart or playing Words With Friends.  They make changes because it’s important to the client, or because they are working diligently at achieving a pixel-perfect product for the end-user.  But whatever their reason, we can be sure they are trying to constantly improve the deliverable with each iteration.  The problem is that this can really cost some serious dev time, and potentially risk a project’s scheduled milestone at the last minute.

What a Sassy Website Does For You

Sass is an incredible progression from the powerful (but somewhat dumb) CSS language, allowing developers to set common stylesheet properties as variables in a single place, which makes cascading changes to those properties across your site into a minimal effort.  You will still write valid CSS in your .scss files, as well as the additional features that Sass provides, and those files are then processed by a Ruby script and produce valid and compact .css files.  Setting up a “watched” folder via a few simple Ruby commands enables you to simply save your file and have your stylesheets automagically processed and exported with zero effort.

The previous versions of Sass were dependent on Haml, and had a very non-CSS syntax that is more compact and preferred among many developers.  Before version 3 Sass used the .sass file extension.  Personally, I’m sticking with my normal CSS syntax which still integrates nicely with the Sass language, and uses a file extension of .scss.  As of version 3, the Sass and Haml projects have been split into separate codebases.

Get to the Code, Already!

This article does not cover the installation of Ruby or Sass/Compass because you can find that information on the Compass Docs pages (including a nicely done video from a while back), as well as many other places out on the intertubes.

Once you have Ruby up and running, and you’ve also installed the Sass and Compass gems, it’s time to get to some code!  The following outline will give you an idea of what we’re going to cover:

  1. Create your Compass project from the command line (remember, Ruby must already be installed on your system).
  2. Add a “_base.scss” file for initializing global variables across stylesheets, or even importing a common framework such as 960gs or Blueprint.
  3. Add one or more .scss files for your application’s styles.  This is where you will write your normal CSS code in addition to your Sass code to be compiled.
  4. Now back to your regularly scheduled coding!

Simple, huh?  Let’s walk through it.

Create Your Compass Project

Once Ruby and the relevant haml (Sass) and compass gems are installed, you can create your project from the command line.

[sourcecode language=”text”]
compass create ~/example-www/styles
[/sourcecode]

I chose to put all my .scss files and resulting stylesheets in a directory called “styles” within my web root, but you can choose to put it anywhere you’d like.  You’ll see that Compass has created a directory structure for me, with a directory for my Sass source files, a few example application files for targeting IE and print/screen CSS media types, a directory where our compiled CSS files will be written, and a configuration file called config.rb where we can manage some of the project output locations and such.

Your web root might look something like this:

Additionally, run the compass watch command on the same folder to have your stylesheets automatically processed and exported each time you save your .scss file to disk.  This is a huge time-saver!

[sourcecode language=”text”]
compass watch ~/example-www/styles
[/sourcecode]

Create a Base Sass File

In the “src” folder, create a new file called “_base.scss” which we will use to set some global variables for all of our stylesheets.  Style properties used throughout the site, like branded colors, common border widths, and other values that multiple elements will use should be declared here.

[sourcecode language=”css”]
/*
_base.scss

Put your global variables, and/or any imported CSS frameworks,
in this file.
*/

$default-text-color: #333;
$default-bg-color: #fff;
$heading-text-color: #7eb5e3;
$fat-border-width: 4px;
$skinny-border-width: 1px;
[/sourcecode]

Add Your Application’s Styles

Your source code belongs in the “src” folder, and you may choose to use the default .scss files created for you when your Compass project was created, or you may delete those files and add your own.  For simplicity, we are going to stick with the existing files.  So let’s add some CSS rules to our “screen.scss” file, which will be the primary stylesheet for styles rendered to the screen media type.

[sourcecode language=”css”]
/*
screen.scss

Your application’s style rules go here, and will be compiled to
a new file within your "stylesheets" folder with the same file
name, except that the file extension will now be ".css".
*/

@import "base";

#content {
color: $default-text-color;
background-color: $default-bg-color;
}
#content-invert-colors{
color: $default-bg-color;
background-color: $default-text-color;
}
#header img.logo {
border: $fat-border-width solid darkblue;
}
#content .tagcloud {
border: $skinny-border-width solid lightblue;
}
[/sourcecode]

Check Out Your Compiled Stylesheets

If you used the compass watch command, then your CSS files have already been compiled automatically when the .scss file(s) were saved!  Just look in the “stylesheets” folder and check out the files – they should be ready to link to directly from your HTML.  Otherwise, you’ll need to run the following command to compile the Sass ad hoc:

[sourcecode language=”text”]
compass compile ~/example-www/styles
[/sourcecode]

Using my Sass example above, the CSS result should look like this:

[sourcecode language=”css”]
/*
screen.css

This is the compiled CSS from our Sass code.
*/

/* line 11, ../src/screen.scss */
#content {
color: #333333;
background-color: white;
}

/* line 15, ../src/screen.scss */
#content-invert-colors {
color: white;
background-color: #333333;
}

/* line 19, ../src/screen.scss */
#header img.logo {
border: 4px solid darkblue;
}

/* line 22, ../src/screen.scss */
#content .tagcloud {
border: 1px solid lightblue;
}
[/sourcecode]

And that’s that!  I’ve described how the Sass/Compass frameworks can improve the workflow for managing stylesheets, and demonstrated a simple example of writing some “Sassy CSS” to create manageable styles that can be updated across multiple files and elements in a snap.  Have fun making your website a little Sass-ier, and let your design buddies know that you’re open for requests!

Further Reading

All My Children and CSS3

I know, I’m just lobbing titles over the fence these days, but it’ll make more sense in a moment.  The SXSW Interactive Festival 2011 is beginning, and I’ll be there with badge on!  Some of the other Springbox crew members will also be there, including several talented individuals who are speaking.  Check out our SXSW 2011 page to catch up on the fun stuff, and grab yourself a request to our super rad party on the balcony of the W Hotel.  Springbox has some of the brightest minds in interactive, and we’ve got an open bar, so … yeah!

While I was HTML-ifying our SXSW page a little while back, I came across the requirement for a nice semi-transparent background for a floating div.  It was to have sharp, fully opaque text, play well with our chosen TypeKit fonts, and partially reveal the cool photo behind it exactly how the designer mocked it up.  This is such a common request, and a cool effect.  But until recently, web developers have always had to work pretty hard to achieve such a simple treatment in the browser.

Opacity has been tough because the default behavior of the CSS opacity property is to not only affect the transparency of the element it is set on, but also all of it’s children.  (See?  Full circle.  Bam.)  But this isn’t the effect we want in this case, and in the past I would resort to some positioning tricks using relative positioning or negative margins to simulate that effect.

Enter CSS3 and the rgba() syntax, which allows as to set opacity using a fourth parameter after the RGB values.  This will only change the opacity of the element it is set on, and it’s children will remain fully opaque!

Only WebKit, Gecko, and Opera browsers currently support this feature, basically all but IE (as usual).  But IE does have a workaround (aka hack) that somewhat works in IE7/8.  Before I give you the code, here are the issues you should be aware of when using this hack:
  1. Requires the infamous hasLayout property in IE to be set to true.  Use “zoom:1;” to cause IE to set this value.
  2. Using the Microsoft filters disables ClearType, and so you may notice blurry text with certain fonts, weights and sizes.
  3. Uses hex code for the alpha level instead of the standard 0 to 255 value.  It’s annoying, but you can do a quick calculation to get the converted hex code.

    Thanks to Kilian Valkhof for this rgba/#ARGB converter code snippet!

Ok, and here’s the CSS code.  I keep it in my screen-ie.css file which is conditionally loaded for IE 8 and below only.

Basically, we have to use Microsoft’s gradient filter to set the same start and end colors (so effectively there is no gradient at all) along with their option for setting the opacity hex code via the first 2 characters of the color string.  IE9 will support rgba(), however.

So that’s how it was done!  Find me at SXSW in Austin this weekend, or follow me on twitter (@grantnorwood).  The weather is beautiful and I know this town is going to pull off another super rad show for developers, designers, and the other brainy and creative types swarming in.  Welcome to my hometown everybody, and be sure to catch plenty of Texas blues with your Texas booze!