Almost bulletproof style for nice underline.
- Work with em and px
- Selection color
- Mixin
- Almost every direction text-shadow for bulletproof foot cuting
- No Compass but Autoprefixer is recommended
A Pen by Cédric Aellen on CodePen.
<h1>Nice <span class="underline">underline</span></h1> | |
<h2>Le Corbeau et le Renard <small class="muted">(with nice underline)</small></h2> | |
<p>Maître Corbeau, sur un arbre perché,<br /> | |
Tenait en son bec un <a href="#" class="underline">fromage</a>.<br /> | |
Maître Renard, par l'odeur alléché,<br /> | |
Lui tint à peu près ce langage :<br /> | |
<a href="#" class="underline">Que vous êtes joli !</a> que vous me semblez beau !<br /> | |
Sans mentir, si votre ramage<br /> | |
Se rapporte à votre plumage,<br /> | |
Vous êtes le Phénix des hôtes de ces bois."<br /> | |
A ces mots le Corbeau ne se sent pas de joie ;<br /> | |
Et pour montrer sa belle voix,<br /> | |
<a href="#" class="underline">Il ouvre un large bec, laisse tomber sa proie.</a><br /> | |
Le Renard s'en saisit, et dit : "Mon bon Monsieur,<br /> | |
<a href="#" class="underline">Apprenez</a> que tout flatteur<br /> | |
Vit aux dépens de celui qui l'écoute :<br /> | |
Cette <a href="#" class="underline">leçon</a> vaut bien un fromage, sans doute. "<br /> | |
Le Corbeau, honteux et confus,<br /> | |
Jura, mais un peu tard, qu'on ne l'y prendrait plus.</p> | |
<p class="italic">Jean de La Fontaine (1621-1695) </p> | |
<h2>Le Corbeau et le Renard <small class="muted">(without nice underline)</small></h2> | |
<p>Maître Corbeau, sur un arbre perché,<br /> | |
Tenait en son bec un <a href="#">fromage</a>.<br /> | |
Maître Renard, par l'odeur alléché,<br /> | |
Lui tint à peu près ce langage :<br /> | |
<a href="#">Que vous êtes joli !</a> que vous me semblez beau !<br /> | |
Sans mentir, si votre ramage<br /> | |
Se rapporte à votre plumage,<br /> | |
Vous êtes le Phénix des hôtes de ces bois."<br /> | |
A ces mots le Corbeau ne se sent pas de joie ;<br /> | |
Et pour montrer sa belle voix,<br /> | |
<a href="#">Il ouvre un large bec, laisse tomber sa proie.</a><br /> | |
Le Renard s'en saisit, et dit : "Mon bon Monsieur,<br /> | |
<a href="#">Apprenez</a> que tout flatteur<br /> | |
Vit aux dépens de celui qui l'écoute :<br /> | |
Cette <a href="#">leçon</a> vaut bien un fromage, sans doute. "<br /> | |
Le Corbeau, honteux et confus,<br /> | |
Jura, mais un peu tard, qu'on ne l'y prendrait plus.</p> | |
<p class="italic">Jean de La Fontaine (1621-1695) </p> |
// import google fonts as a Typekit fallback | |
@import url(http://fonts.googleapis.com/css?family=Merriweather); | |
// variables | |
$base-text-color: #333; | |
$base-text-font-family: 'kinesis-pro-3', 'Merriweather', serif; | |
$base-background-color: #fff; | |
$base-primary-color: #ff0000; | |
$base-font-size: 24px; | |
// Transform px to em | |
@function em($px, $base: $base-font-size) { | |
@return ($px / $base) * 1em; | |
} | |
// Transform em to px | |
@function px($em, $base: $base-font-size) { | |
@return ($em * $base) * 1px; | |
} | |
// Underline mixin | |
// | |
// If you set the variable in ems, be carefull. Firefox doesn't like dimensions <1px. | |
// $var * base-font-size > 1px | |
@mixin underline ($underline-color: $base-text-color, $position: 3px, $width: 1px, $background-color: $base-background-color, $cut-distance: 1px, $font-size: $base-font-size) { | |
// remove classic underline | |
text-decoration: none; | |
// warn if underline is thinner than 1px | |
@if unit($width)==px { | |
@if $width < 1px { | |
@warn "Underline is thinner than 1px. Some browsers may not display it." | |
} | |
} | |
@if unit($width)==em { | |
// FIXME: if underline() contain em values, there's a bug with the following condition | |
@if px($width) < 1px { | |
@warn "Underline is thinner than 1px. Some browsers may not display it." | |
} | |
} | |
// if unit is in px, tranform it in em | |
@if unit($position)==px { | |
$position: em($position, $font-size); | |
} | |
@if unit($width)==px { | |
$width: em($width, $font-size); | |
} | |
@if unit($cut-distance)==px { | |
$cut-distance: em($cut-distance, $font-size); | |
} | |
// the underline | |
background-image: linear-gradient(to top, $background-color, $background-color $position, $underline-color $position, $underline-color $position+$width, $background-color $position+$width); | |
// text-shadow | |
// why so much ?! -> http://dsh.re/14297 | |
$precision: 5; | |
$all: (); | |
$delta-distance: $width * 2 / ($precision - 1); | |
// from left to right | |
@for $i from 0 through ($precision - 1) { | |
// from top to bottom | |
@for $y from 0 through ($precision - 1){ | |
$all: append($all, (-$width)+$delta-distance*$i ((-$width)+$delta-distance*$y) 0 $background-color, comma) | |
} | |
} | |
text-shadow: $all; | |
} | |
.underline { | |
@include underline(); | |
// When underline text is selected, the shadow color is the same as | |
// the selection color. | |
&::selection { | |
@include underline($base-text-color, 4px, 1px, lighten($base-primary-color, 30%)); | |
} | |
} | |
a.underline:hover { | |
@include underline($base-primary-color); | |
} | |
// housekeeping | |
body { | |
max-width: 25em; | |
margin: 0 auto; | |
padding: $base-font-size$base-font-size/2; | |
font-family: $base-text-font-family; | |
font-size: ($base-font-size / 16px) * 1em; | |
line-height: 1.5; | |
background-color: $base-background-color; | |
color: $base-text-color; | |
-moz-osx-font-smoothing: grayscale; | |
-webkit-font-smoothing: antialiased; | |
font-feature-settings: "liga", "clig", "onum"; | |
} | |
a { | |
color: $base-text-color; | |
&:hover { | |
color: $base-primary-color; | |
} | |
} | |
::selection { | |
background-color: lighten($base-primary-color, 30%); | |
} | |
.muted { | |
color: #999; | |
} | |
h1, | |
h2, | |
.italic { | |
font-style: italic; | |
} |
Almost bulletproof style for nice underline.
A Pen by Cédric Aellen on CodePen.