Intermediate Articles

(Better) Tabs with Round Out Borders

A good-looking tab control usually has one feature that I've always found impossible to reproduce without images: borders that bend to the outside at the bottom of each tab. In this article I would like to show how you can use the CSS :before and :after pseudo elements to create this effect without using images.

Columns and the Greatest Common Divisor

I was recently putting together some CSS for columns. There was a few pre-determined widths that the columns needed to accommodate. For whatever reason (maybe because every grid framework in the world is this way) my mind went right to trying to find a common building block size. All columns are either the size of one building block or a multiple of a building block with gutter widths added. (more…)

Full Browser Width Bars

Yet another useful thing that pseudo elements can do for us: allow us to create full browser width header bars without using internal non-semantic wrappers.

Case Study: jQuery Fixer Upper

We'll look at some jQuery code that a CSS-Tricks reader posted in the forums. We'll suggest ways to improve the code to make it more efficient and more extensible. We'll also make some guesses about the HTML that it goes with and discuss improvements there.

Styling Texty Inputs Only

A CSS3 technique for selecting only texty inputs, without the burdon of listing every single attribute selector for every single new HTML5 input type. Plus alternates.

Keep Margins Out of Link Lists

When building a menu or other list of links, it's generally a good practice to use display: block; or display: inline-block; so that you can increase the size of the link target. The simple truth: bigger link targets are easier for people to click and lead to better user experience.


Transparent Borders with background-clip

Have you ever seen an element on a page with transparent borders? I think Facebook originally popularized it giving birth to lightbox plugins like Facebox. I don't think Facebook sports the look anymore, but it's still rather neat.

You might think it would be as simple as this:

#lightbox {
   background: white;
   border: 20px solid rgba(0, 0, 0, 0.3);

However, setting a transparent border on an element will reveal the elements own background underneath the border.

In the screenshot above, the borders use RGBa to be transparent, but they appear solid gray because they are only revealing the solid white background of itself below.

Fortunately there is a CSS3 property to save us! It's called background-clip and it's used specifically to specify which portion of the box model should be utilized to display the background. It does what it sounds like it does, it cuts off the background at the specified portion of the box. There are three values it can have, and vendor prefixes do get involved. Here are the three settings it could have. You wouldn't use them all at once, this is for convenience of displaying only:

#lightbox {

  -moz-background-clip: border;     /* Firefox 3.6 */
  -webkit-background-clip: border;  /* Safari 4? Chrome 6? */
  background-clip: border-box;      /* Firefox 4, Safari 5, Opera 10, IE 9 */
  -moz-background-clip: padding;     /* Firefox 3.6 */
  -webkit-background-clip: padding;  /* Safari 4? Chrome 6? */
  background-clip: padding-box;      /* Firefox 4, Safari 5, Opera 10, IE 9 */
  -moz-background-clip: content;     /* Firefox 3.6 */
  -webkit-background-clip: content;  /* Safari 4? Chrome 6? */
  background-clip: content-box;      /* Firefox 4, Safari 5, Opera 10, IE 9 */

Here are the schematics:

So I'm sure you see where I'm going here... if we set the background-clip to the padding-box, the white background will end before the border and the transparency will lay over other content acheiving the look we are going for!

View Demo

Related: background-origin

In our lightbox example, it's most likely that the background is a solid color. In that case, background-origin is rather irrelevant, as nobody will ever be able to tell where the color "started" from. However, if the background of the element is an image, it can be quite important where the origin point of the background starts.

This is related to background-clip, because if the background-clip is the padding-box but the background-origin is left at the default border-box, some of the background-image will be cut off, which may or not be desireable.

Here is the schematic:

And a visual example:

Browser Compatibility

Works in: Safari 5, Chrome 7, Firefox 3.6+, Opera 10, IE 9

I only tested these modern browsers and support is good. It may (and likely does) go back a bit further in the non-IE browsers.

If you'd more complete browser compatibility, you can always go with the double-div method.

<div id="lightbox">
   /* Set transparent background with PNG
       add padding to push inside box inward */

   <div id="lightbox-inside">
      /* Set white background in here */


Another advantage to the double-div method is that you could achieve truly rounded borders. Unfortunately with the background-clip method, the outer border is round but the edge of the background stays straight-cornered.

Too bad we don't have something like background-radius to fix it:

   border-radius: 16px;
   padding: 8px;

   /* NOT REAL */
   background-radius: 8px;


20px of border was fine, but when I tried 30px, these mini boxes of death showed up in Safari 5.

In Chrome, little diagonal lines were present at any border width up to 20px.

Above 20px border, the corners completely darken.

Without border-radius, darkened corner boxes are always visible.


Thanks to Alex Hall for the original idea and help.

Here's a simple demo showing the different values of background-clip as well:

Check out this Pen!

and background-origin:

Check out this Pen!

Adding Stroke to Web Text

Fonts on the web are essentially vector based graphics. That's why you can display them at 12px or 120px and they remain crisp and relatively sharp-edged. Vector means that their shape is determined by points and mathematics to describe the shape, rather than actual pixel data. Because they are vector, it would make sense if we could do things that other vector programs (e.g. Adobe Illustrator) can do with vector text, like draw a stroke around the individual characters. Well, we can! At least in WebKit. Example:

h1 {
   -webkit-text-stroke-width: 1px;
   -webkit-text-stroke-color: black;

Or shorthand:

h1 {
   -webkit-text-stroke: 1px black;

Right away, I'm sure you are thinking: "Cool, but only WebKit supports, this, so if I set my text color to white and my background is white, the stroke makes it look cool in WebKit but disappears in other browsers!"

WebKit has your back on that one, you can set the text color with another proprietary property, so you're safe for all browsers:

h1 {
   color: black;
   -webkit-text-fill-color: white; /* Will override color (regardless of order) */
   -webkit-text-stroke-width: 1px;
   -webkit-text-stroke-color: black;

Shown here with @font-face font Anime Ace 2 by Nate Piekos:

Properly stroked!

Fallback to solid color. Shown here in Firefox


We can take this a bit further by not relying on the WebKit proprietary entirely. We can use the text-shadow property (supported in Firefox, Opera, and IE 10 as well) and simulate a stroke. We'll use four shadows, each 1px offset of black with no spread, one each to the top right, top left, bottom left, and bottom right. We'll use remove the WebKit propreitary -webkit-text-fill-color in favor of color since we're cross-browser compatible now. The only holdout would be IE9 and down, which of course you can use IE specific stylesheets to account for.

h1 {
  color: white;
   -1px -1px 0 #000,  
    1px -1px 0 #000,
    -1px 1px 0 #000,
     1px 1px 0 #000;

This is a stroke using all text-shadow. Pretty close to just as good as a real stroke. The primary issue is that you can only get 1px of stroke this way. Any more, and you see gaps. Any more with WebKit text stroke and there is issues too though, so it's kind of a horse apiece.


Using both a stroke and a shadow can be a great effect. Let's toss on a WebKit stroke, the all-around text-shadow stroke, as well as a deeper text-shadow stroke.

h1 {
   -webkit-text-stroke: 1px black;
   color: white;
       3px 3px 0 #000,
     -1px -1px 0 #000,  
      1px -1px 0 #000,
      -1px 1px 0 #000,
       1px 1px 0 #000;

Lookin' good


If you are familiar with Adobe Illustrator, you may know that you can align a stroke on the inside of a shape, outside, or centered. That option looks like this in the palette:

From left to right: center, inside, outside

For reasons unbeknownst to me, text in Illustrator can only be set to center stroke alignment as well. Once you expand the text into regular vector paths though, all three options become available. Reminder from Sam Frysteen: add a new stroke in the appearance panel and move it below your text (basically mimics outside stroke alignment).

From top to bottom: inside, centered, outside.

Only outside text stroke alignment looks any good at all to me. It's unfortunate, both for CSS and for Illustrator, that the unchangeable default is centered. The solution is just not to go too crazy with the thickness of your stroke border and things should be OK. Note: the text-shadow-only solution doesn't have this problem, but also is unable to stroke any more than 1px.

If you use a pseudo element, you can stroke the same text behind the original text and kinda fake outside stroke.

What we can't do

There are other things that vector based graphics programs can do with text. You can squish the letter horizontally / stretch them vertically. This type of text treatment is almost universally frowned upon, so no big loss that we can't do that. You can also set type on an irregular line (like around a circle). It certainly would be cool to do this with web text. Perhaps we could set text to follow the border path of its parent element.

p.circular {
  width: 200px;
  height: 200px;
  border-radius: 100px;
  /* NOT REAL */
  text-align: border-path;

In Illustrator, we can also tell a stroke how to handle sharp corners: rounded, beveled, or mitered. These can have nice effects, are not possible on the web. However, the WebKit handling of corners is pretty nice at its default (whatever it is), and arguably nicer than any of the options in Illustrator.


For the record, you can use any type of color value for the color of WebKit stroke (hex, rgba, hsla, keyword). That means transparent strokes if you want them, which indeed to "stack" in that if strokes overlap each other (common) they will be darker.

As far as WebKit keyframe animation, the stroke color will animate but the stroke width will not.

/* Only the color will change, not the width */
@-webkit-keyframes colorchange {
	0% {
		-webkit-text-stroke: 10px red;
	100% {
		-webkit-text-stroke: 20px green;

Demo & Download

View Demo   Download Files


Thanks to Hendra Susanto and Cory Simmons for sending in ideas and demos.