Articles by
Marie Mosley

Writer, Almanac Adjuster, Chief of the Comma Police

text-decoration-color

The text-decoration-color property sets the color of the underline, overline, or line-through on text with the text-decoration property applied. It can also set the underline color on links.

a {
  text-decoration-color: #E18728;
}

Values

text-decoration-color can inherit or accept any CSS color value, including named colors, HEX colors, RGBa, and HSLa.

Shorthand

In browsers that support text-decoration-style and text-decoration-color you can add a color to a text-decoration shorthand property:

.underlined {
  text-decoration: underline dotted red;
}

Currently only Firefox supports this unprefixed. Safari supports it with the -webkit prefix. Chrome also needs the -webkit prefix and experimental web platform features enabled in Chrome flags.

Demo

The text-decoration-color in this demo works in the current versions of Firefox and Safari. It will also work in Chrome with the "experimental Web Platform features" flag enabled.

See the Pen text-decoration-color by CSS-Tricks (@css-tricks) on CodePen.

Related

More Information

Browser Support

Chrome Safari Firefox Opera IE Android iOS
31† 7.1* 6.0‡ None None None 8*

† with the "experimental Web Platform features" turned on in chrome://flags. Chrome 31 needed -webkit- prefix. We tested Chrome 50 and it only worked unprefixed.
‡ 6+ with -moz prefix, unprefixed as of 36.

text-decoration-style

The text-decoration-style property sets the style of the underline on links and the underline, overline, or line-through on any text with text-decoration applied.

a {
  text-decoration-style: solid;
}

Values

  • solid: the default. Decoration is a single solid line.
  • double: Decoration is a pair of solid lines.
  • dotted: Decoration is a dotted line.
  • dashed: Decoration is a dashed line.
  • wavy: Decoration is a wavy line.

Demo

At the time of this writing, text-decoration-style is only officially supported in Firefox. It will also work in Chrome browsers with the experimental web platform features flag enabled.

See the Pen text-decoration-style by CSS-Tricks (@css-tricks) on CodePen.

Shorthand

In browsers that support text-decoration-style and text-decoration-color you can add a decoration style to a text-decoration shorthand property:

.underlined {
  text-decoration: underline dotted red;
}

Currently only Firefox supports this unprefixed. Safari supports it with the -webkit prefix. Chrome also needs the -webkit prefix and experimental web platform features enabled in Chrome flags.

Related

More Information

Browser Support

Chrome Safari Firefox Opera IE Android iOS
31 * None 6 † None None None None

* only with experimental web platform features flag enabled

† Firefox 6+ with -moz prefix, 36+ unprefixed.

text-decoration-skip

The text-decoration-skip property specifies where a text underline, overline, or strike-through should break. This improves legibility of decorated text and corrects punctuation grammar for some languages.

Here's one example:

a {
  text-decoration-skip: ink;
}

Heads up! The ink value has been changed to an entirely new property, text-decoration-skip-ink: auto;.

If your browser supports this property then you’ll notice here that the descenders of each character (like “y” and “p”) have little white spaces around the border:

See the Pen text-decoration-skip by CSS-Tricks (@css-tricks) on CodePen.

If your browser doesn’t support this feature then this is what you ought to expect from the property in a supporting browser:

This may not be what text-decoration-skip: ink; actually looks like when it gets implemented, but this descender-clearing style is part of Marcin Wichary's vision for a perfect underline as he lays out here.

Values

  • objects: the default. Decoration line skips inline objects, like images or inline-block elements.
  • none: decoration line crosses everything, including inline objects that would normally be skipped.
  • spaces: decoration line skips spaces, word-separator characters, and any spaces set with letter-spacing or word-spacing.
  • ink: decoration line skip glyphs or descenders.
  • edges: decoration line starts slightly after the content's starting edge and ends slightly before the content's ending edge. This property was designed to keep two side-by-side underlined elements from looking like they're sharing a single underline. This is useful for text in the Chinese language, which uses underlining for punctuation.
  • box-decoration: decoration line skips over inherited margin, border, and padding.

Update: it looks like the trailing-spaces value has now been deprecated, since it can no longer be found in the spec.

Since this property is not supported by any browser yet there's no demo, but here's an example of how each of the values could look once text-decoration-skip is implemented.

text-decoration-skip illustration

text-decoration-skip in OSX and iOS

In late 2014, Apple made a change to text-decoration in Safari and iOS browsers that mimics how text-decoration-skip: ink; should work. Though none of the text-decoration-skip values are officially implemented yet, you can disable this default behavior with -webkit-text-decoration-skip: none;.

See the Pen -webkit-text-decoration-skip: none; by CSS-Tricks (@css-tricks) on CodePen.

Related

More Information

Browser Support

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeOperaFirefoxIEEdgeSafari
675261NoNoTP*

Mobile / Tablet

iOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox
11.3*NoNo626457

text-align-last

text-align-last lets you control the alignment of the last (or only) line of text right before a forced line break — for example the end of a paragraph or the line right before a <br> tag.

.intro-graph {
  text-align-last: center;
}

At the time of this writing, only Mozilla browsers and Internet Explorer support text-align-last (with vendor prefixes), and each has a slightly different implementation. The property was supposed to start working in Chrome 35, but as of Chrome 40 it still requires the experimental web platforms flag. More detail on browser implementations in the Points of Interest.

Values

  • left aligns the last line of text to the left of the container.
  • rightaligns the last line of text to the right of the container.
  • center centers the last line of text within the container.
  • justify justifies the last line of text so it spans the full width of the container, inserting space between words if needed to increase the line length.
  • start aligns the text to the "start" of the line based on the direction of the text — left for LTR languages, right for RTL languages.
  • end aligns the last line to the "end" of the line based on the direction of the text — right for LTR languages, left for RTL languages.
  • auto the default. Aligns the last line of text to match the element's text-align property, if it is set. If it is not set, auto aligns the text to the start.
  • inherit applies the text-align-last property of the parent element.

Demo

This demo shows the different text-align-last values in action. Note: Internet Explorer does not support the start or end values.

See the Pen text-align-last by CSS-Tricks (@css-tricks) on CodePen.

Points of Interest

In Internet Explorer, text-align-last only works when the text-align of the rest of the text in the selected element is set to justify. Also, IE does not recognize the start or end value.

In Mozilla browsers, text-align-last will work on the last line before a forced line break even if there is no alignment specified for the rest of the text in the element.

It's also worth knowing that text-align-last sets the alignment for all last lines within the selected element, not just the absolute last line of text. So, for example, if you have a div with five paragraphs in it, your text-align-last declaration will apply to the last line of each of the paragraphs.

If you want to use text-align-last on only the very last line in the container, you may be able to use :last-child or :last-of-type. Your CSS would look something like this:

#center-only-last p:last-child {
  -ms-text-align-last: center;
  -moz-text-align-last: center;
  text-align-last: center;
}

In the demo below, the left side shows text-align-last: center; applied to a div with multiple paragraphs inside it. Notice that the last line of each paragraph is centered. The right side shows text-align-last: center; applied only to the last paragraph inside the div using :last-child.

See the Pen text-align-last by CSS-Tricks (@css-tricks) on CodePen.

Related

More Information

Browser Support

Chrome Safari Firefox Opera IE Android iOS
35+ with experimental flags Nope 34+ (prefixed) Nope 5.5+ (prefixed) Nope Nope

:blank

The :blank pseudo-class builds upon the :empty pseudo-class. Like :empty, :blank will select elements that contain nothing at all, or contain only an HTML comment. But, :blank will also select elements that include whitespace, which :empty will not.

p:blank {
  display: none;
}

p:blank will select these paragraphs, just like p:empty would:

<p></p>
<p><!-- nothing but a comment--></p>

And it will also select these paragraphs, which p:empty would not:

<p> </p>
<p>

  <!--a comment and some whitespace-->
  
</p>

At the time of this writing, :blank is part of the CSS Selectors Level 4 draft, and is not supported by any browser. Mozilla supports its own version of :blank under a different, vendor-prefixed name: :-moz-only-whitespace. The demo below includes Mozilla's version, and will only work in Mozilla browsers for now.

See the Pen :blank and :-moz-only-whitespace by mariemosley (@mariemosley) on CodePen.

Related

More Information

Browser Support

Chrome Safari Firefox Opera IE Android iOS
Nope Nope As :-moz-only-whitespace Nope Nope Nope Nope

border-image

border-image is a shorthand property that lets you use an image or CSS gradient as the border of an element.

.module {
  border-image: url(border.png) 25 25 round;
}

The border-image property can be applied to any element, except internal table elements (e.g. tr, th, td) when border-collapse is set to collapse.

Properties

The only required property for the border-image shorthand is border-image-source. The other properties default to their initial values if they're not specified. These are the border-image properties in order:

border-image-source

.module {
  border-image-source: url(border.png);
}

This property specifies the source for the border image. This can be a URL, data URI, CSS gradient, or inline SVG (though support is limited for inline SVG, see SVG usage notes).

The initial value is none.

border-image-slice

.module {
  border-image-source: url(border.png);
  border-image-slice: 20;
}

The values of this property tell the browser where to “slice” the image to create the pieces of the border. The image is divided into 9 sections — the four corners, the four sides, and the center.

Border image with slice lines marked in red (enlarged to show detail).

The property accepts up to four positive unitless numbers or percentages, and an optional fill keyword. The initial value is 100%.

Unitless numbers measure the slice by pixels on a raster image, and by coordinates on an SVG. A percentage value is relative to the size of the image. For example, on a raster image that is 100px x 100px, 10% from any side of the image is 10px. See the usage notes on SVG for more information about how percentages work on SVG images.

The values measure from the top, right, bottom, and left edges of the image (in that order). If one value is missing, its value defaults to the value of its opposite side — for example if the left value is missing, but the right value is set at 10px, the left value becomes 10px too.

By default, the center of the source image is discarded. But, when the fill keyword is used, it's applied to the background of the bordered element instead.

border-image-width

.module {
  border-image-source: url(border.png);
  border-image-slice: 20;
  border-image-width: 20;
}

This property sets the width of the border image. It accepts a percentage value, a positive unitless number, or the keyword auto.

The values are for the top, right, bottom, and left sides of the element (in that order). If one value is missing, it is drawn the same as its opposite value.

For this property, percentage values are relative to the size of the border image area, while a unitless number is multiplied with the border-width.

The initial value is 1, so if this value is not set but there's a border or border-width declaration for the element, the border image will be drawn at that width.

The auto keyword tells the browser to use either the size of the border-image-slice if available, or the size of the border-width.

border-image-outset

.module {
  border-image-source: url(border.png);
  border-image-slice: 20;
  border-image-width: 20;
  border-image-outset: 1;
}

The value for this property specifies how far the border image area extends past the border box. The initial value is 0. The property accepts up to four positive length values or unitless numbers. Length values are absolute measurements, while a unitless number is multiplied with the border width to compute the outset value, similar to how unitless numbers work for border-image-width.

border-image-repeat

.module {
  border-image-source: url(border.png);
  border-image-slice: 20;
  border-image-width: 20;
  border-image-outset: 1;
  border-image-repeat: round;
}

This property controls how the image is repeated to fill the area of the border.

You can specify up to two values for this property. If one value is specified, it's applied to both the horizontal and vertical sides of the border. If two are specified, the first is applied to the horizontal sides and the second is applied to the vertical sides.

Values
  • stretch: the initial value. The border image is stretched as needed to fill the area.
  • repeat: the image tiles to fill the area, dividing tiles if necessary.
  • round: the image tiles to fill the area, and is rescaled if necessary to avoid dividing tiles.
  • space: the image tiles to fill the area. If the area can't be filled with whole tiles, space is inserted around the tiles for an even fit. Note: this value is not implemented by any browser yet.

Try out the different border-image-repeat values in this demo (space is included for future compatibility only; it doesn't work as specified in any browser yet):

See the Pen border-image demo: border-image-repeat tester by CSS-Tricks (@css-tricks) on CodePen.

Using Gradients for Border Images

All of the browsers that support border-image support CSS gradients too. You can use gradients of any type to make your border. This demo shows a repeating linear gradient making a striped border (hover it to see the stripe colors swap).

See the Pen border-image demo: repeating linear gradient border by CSS-Tricks (@css-tricks) on CodePen.

The browser will slice the gradient like it would slice a square image with width and height equal to the border-image-width.

Using SVG for Border Images

The biggest difference between using raster images and SVG for border-image is in how the slices are measured.

Unitless values represent coordinates on SVG images.

Percentage values are relative to the size of the image.

If the SVG doesn't have a defined size, it is sized with the default sizing algorithm, which will use the border image area set by the border-image-outset as the default size. This can be confusing in practice, so it's helpful to set a size for the SVG when possible.

SVG in an Image Source URL

You can link an SVG file as the border-image-source the same way you'd link a raster image:

.module {
  border-image-source: url(border.svg);
}

This is probably the best method for using SVG as border images. It's well-supported — all modern browsers that support border-image will accept a linked SVG as the border-image-source.

Inline

You can Base64 encode an SVG border image, or write the SVG markup directly into the border image source, but both methods have fairly significant issues.

Base64 SVG has enough problems to merit its own article: Probably Don't Base64 SVG.

Writing SVG image markup directly into a border-image declaration also has complications; Internet Explorer will not recognize it, and support in Firefox is quirky (see Bug 619500).

The border image in this demo is an inline SVG gradient. If you check out the “CSS” tab, you'll notice that the markup has to be carefully composed — note the double quotes around the markup, the single quotes inside the markup, and the escaped octothorpe (#) characters in the hex colors.

See the Pen border-image demo: Inline SVG by CSS-Tricks (@css-tricks) on CodePen.

Making a Border of a Single Repeating Image

Bordering an element with a single repeating image is something that seems like it should be easy with a property called border-image, but the process for actually doing that is somewhat counter-intuitive.

Let's say, for example, that you want to border an element with a repeating heart icon. You can't do that with a image of a single heart. Instead, you have to make an image of a “frame” of hearts arranged as you'd like them to appear in the border, then slice that image.

Eight hearts in a "frame" image, enlarged to show detail. The red lines indicate slices.

If you think that sounds preposterous, you're in good company. There was a lengthy discussion of the subject on Eric Myer's blog a few years ago where many frontend development greats weighed in.

In this demo, a heart repeats around the border of the div. The border-image-source image is a composite image of eight of the same heart icon, sliced so that the full heart shape is used on each side of the element.

See the Pen border-image demo: icon border by CSS-Tricks (@css-tricks) on CodePen.

More Usage Notes

Though support for border-image has improved — it's supported unprefixed in all current browser versions — setting a fallback border style is still worthwhile. Your fallback border will show on browsers that don't support border-image, or if the image fails to load.

Unlike some of the other border properties, border-image can't be animated. It also can't be styled with border-radius.

If you declare a border-image-source and a border width or border-image-width without any slices, the entire unsliced image will be placed at the four corners of the element, scaled to your specified width.

Related

More Information

More Demos

  • Also from Dudley Storey, Practical border-image: responsive picture frame, a CodePen demo. This is a good example of using a border image sensibly on a responsive image. Notice that the “frame” is removed at smaller screen sizes.
  • True dotted borders using SVG and border-image, a Pen by Lucas Lemonnier. A solution for the ugly square “dotted” border, this method gives you real round dots!
  • gradient button, a Pen by CodePen user GSSxGSS. A pretty example of a linear gradient as a border image.
  • Film Strip, a Pen by Nick Pettit. Perhaps not the most practical demo, this is a fun, arty example of what you can do with border-image.

Browser Support

border-image originally required vendor prefixes on all browsers that supported it. Now it works unprefixed in the latest version of all browsers. This table shows both the earliest prefixed support and the earliest unprefixed support where applicable.

Chrome Safari Firefox Opera IE Android iOS
7*, 16 3*, 6 3.5†, 15 10.5, 15‡ 11 2.1*, 4.4 3.2*, 6

* with -webkit prefix.
† with -moz prefix.
‡ 10.5 - 14 series with -o prefix; fill keyword is not supported in any version.

Box Sizing

The box-sizing property can make building CSS layouts easier and a lot more intuitive. It's such a boon for developers that here at CSS-Tricks we observe International Box-Sizing Awareness Day in February.

But, how is it so helpful and beloved that it deserves its own internet holiday? Time for a little bit of CSS history.

Box Model History

Since the dawn of CSS, the box model has worked like this by default:

width + padding + border = actual visible/rendered width of an element's box

height + padding + border = actual visible/rendered height of an element's box

This can be a little counter-intuitive, since the width and height you set for an element both go out the window as soon as you start adding padding and borders to the element.

Back in the old days of web design, early versions of Internet Explorer (<= IE6) handled the box model differently when it was in "quirks mode". The "quirks" box model worked like this: width = actual visible/rendered width of an element's box height = actual visible/rendered height of an element's box The border and padding values were moved inside the element's box, cutting into the width/height of the box rather than expanding it.

The box at the top shows the default box model. The box at the bottom shows what was once the "quirks mode" interpretation of the box model.

Some people preferred this "quirky" interpretation of the box model and considered it more intuitive. It's a valid point. Having the actual visible width of a box turn out differently from what you declared in the CSS is a bit mind bending.

But, in the days of fixed-width design, it wasn't particularly complicated to work with the default box model once you understood it. You could do a bit of arithmetic to figure out how many pixels you needed to trim off of an element's declared width or height to accommodate its padding and border. The problem for present-day developers is that those absolute pixel lengths don't translate to responsive design, so the same math doesn't apply anymore.

As responsive design (or, as it was once known, "fluid" or "liquid" layout) started to gain popularity, developers and designers wished for an update to the box model. The great designer Jon Hicks, known for his excellent fluid width designs, had this to say on the subject in the CSS Wishlist we put together in 2008:

I would love a different box model! I find it bizarre that padding and border add the width of an object, and would love to be able to give something like a textarea 100% width and 3px padding without worrying what it’s going to do the layout. Perhaps something like padding-inside as a new selector?

In that vein I also wish I could specify a 100% width for an element, minus a set fixed width. Again, very useful when creating fluid designs with form elements!

Present-Day box-sizing

Those wishes were granted when the box-sizing property was introduced in CSS3. Though box-sizing has three possible values (content-box, padding-box, and border-box), the most popular value is border-box.

Today, the current versions of all browsers use the original "width or height + padding + border = actual width or height" box model. With box-sizing: border-box;, we can change the box model to what was once the "quirky" way, where an element's specified width and height aren't affected by padding or borders. This has proven so useful in responsive design that it's found its way into reset styles.

At this point you may be asking yourself, "Is it possible that Old IE did something right?" Plenty of people think so.

Demo

This demo shows how border-box can help make responsive layouts more manageable. The parent div's width is 50%, and it has 3 children with different widths, padding, and margins. Click the border-box button to get all the children in the right place inside the parent.

See the Pen Box Sizing Layout Demo by CSS-Tricks (@css-tricks) on CodePen.

Good, Better, and (Probably) Best box-sizing Reset Methods

The "Old" border-box Reset

The earliest box-sizing: border-box; reset looked like this:

* {
  box-sizing: border-box;
}

This works fairly well, but it leaves out pseudo elements, which can lead to some unexpected results. A revised reset that covers pseudo elements quickly emerged:

Universal Box Sizing

*, *:before, *:after {
  box-sizing: border-box;
}

This method selected pseudo elements as well, improving the normalizing effect of border-box. But, the * selector makes it difficult for developers to use content-box or padding-box elsewhere in the CSS. Which brings us to the current frontrunner for best practice:

Universal Box Sizing with Inheritance

html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}

This reset gives you more flexibility than its predecessors — you can use content-box or padding-box (where supported) at will, without worrying about a universal selector overriding your CSS. We went into more depth on this technique and the reasoning behind it in "Inheriting box-sizing Probably Slightly Better Best Practice". One potential gripe with it is that box-sizing isn't normally inherited, so it's specialized behavior, not quite the same as something you'd normally put in a reset.

Vendor Prefixes

Every current browser supports box-sizing: border-box; unprefixed, so the need for vendor prefixes is fading. But, if you need to support older versions of Safari (< 5.1), Chrome (< 10), and Firefox (< 29), you should include the prefixes -webkit and -moz, like this:

html {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
*, *:before, *:after {
  -webkit-box-sizing: inherit;
  -moz-box-sizing: inherit;
  box-sizing: inherit;
  }

Known Issues

box-sizing: border-box; is supported in the current versions of all major browsers. The less-commonly used padding-box is only supported in Firefox at the moment. There's more comprehensive information about browser support in our box-sizing almanac entry.

There are a few issues with older versions of Internet Explorer (8 and older). IE 8 doesn't recognize border-box on elements with min/max-width or min/max-height (this used to affect Firefox too, but it was fixed in 2012). IE 7 and below do not recognize box-sizing at all, but there's a polyfill that can help.

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag