<!-- I made this pen to try out and illustrate some of the subtle shadow effects you can create using just text-shadow and transitions. The pattern effect also uses a small piece of SVG.
Inspired by this animated gif I saw on dribbble (https://dribbble.com/shots/1881907-Love?list=shots&sort=recent&timeframe=now&offset=18).
I’ve included the Sass mixins I use to make the text-shadow effect, but you could also just use compass which has these mixins baked straight in.
The CSS only effects (first 4) work in Chrome/Firefox/Safari/IE10+.
The final pattern effect works perfectly in Chrome, Firefox and IE seems to lose the text-shadow for some reason and it completely flips out in Safari!
-->
<h1>A collection of CSS Text shadow and pattern effects <a href="https://twitter.com/AshNolan_" target="blank">created by @AshNolan_</a></h1>
<h2 class="headingOuter">Push down (shadow effect)</h2>
<div class="headingWrapper color-bright">
<a href="" class="header header--pushDown header--shadow" title="HOVER ME">HOVER ME</a>
</div>
<div class="headingWrapper">
<a href="" class="header header--pushDown header--shadow" title="HOVER ME">HOVER ME</a>
</div>
<h2 class="headingOuter">Raise up (shadow effect)</h2>
<div class="headingWrapper color-bright">
<a href="" class="header header--raiseUp header--shadow">HOVER ME</a>
</div>
<div class="headingWrapper">
<a href="" class="header header--raiseUp header--shadow">HOVER ME</a>
</div>
<h2 class="headingOuter">Push down (merging into page)</h2>
<div class="headingWrapper color-bright">
<a href="" class="header header--pushDown">HOVER ME</a>
</div>
<div class="headingWrapper">
<a href="" class="header header--pushDown">HOVER ME</a>
</div>
<h2 class="headingOuter">Raise up (emerging from page)</h2>
<div class="headingWrapper color-bright">
<a href="" class="header header--raiseUp">HOVER ME</a>
</div>
<div class="headingWrapper">
<a href="" class="header header--raiseUp">HOVER ME</a>
</div>
<h2 class="headingOuter">Raised up (emerging from bg) with pattern</h2>
<div class="headingWrapper color-bright">
<a href="#" class="header header--raiseUp header--svg">
<svg>
<defs>
<linearGradient id="stripedColor" x1="0" x2="0" y1="0%" y2="4%" spreadMethod="repeat">
<stop offset="0%" stop-color="#e62915"/>
<stop offset="50%" stop-color="#e62915"/>
<stop offset="51%" stop-color="#fff"/>
<stop offset="99%" stop-color="#fff"/>
<stop offset="100%" stop-color="#e62915"/>
</linearGradient>
</defs>
<text y="1.2em">Hover Me</text>
</svg>
</a>
</div>
<div class="headingWrapper">
<a href="#" class="header header--raiseUp header--svg">
<svg>
<defs>
<linearGradient id="striped" x1="0" x2="0" y1="0%" y2="4%" spreadMethod="repeat">
<stop offset="0%" stop-color="#e62915"/>
<stop offset="50%" stop-color="#e62915"/>
<stop offset="51%" stop-color="#fff"/>
<stop offset="99%" stop-color="#fff"/>
<stop offset="100%" stop-color="#e62915"/>
</linearGradient>
</defs>
<text y="1.2em">Hover Me</text>
</svg>
</a>
</div>
/*
The following mixin is taken and edited from this pen - https://codepen.io/hugo/pen/xzjGB
I have added outlineColor to allow the addition of a text-shadow outline for the text.
*/
@function pow($number, $exp) {
$value: 1;
@if $exp > 0 {
@for $i from 1 through $exp {
$value: $value * $number;
}
}
@else if $exp < 0 {
@for $i from 1 through -$exp {
$value: $value / $number;
}
}
@return $value;
}
@function fact($number) {
$value: 1;
@if $number > 0 {
@for $i from 1 through $number {
$value: $value * $i;
}
}
@return $value;
}
@function pi() {
@return 3.14159265359;
}
@function rad($angle) {
$unit: unit($angle);
$unitless: $angle / ($angle * 0 + 1);
// If the angle has 'deg' as unit, convert to radians.
@if $unit == deg {
$unitless: $unitless / 180 * pi();
}
@return $unitless;
}
@function sin($angle) {
$sin: 0;
$angle: rad($angle);
// Iterate a bunch of times.
@for $i from 0 through 10 {
$sin: $sin + pow(-1, $i) * pow($angle, (2 * $i + 1)) / fact(2 * $i + 1);
}
@return $sin;
}
@function cos($angle) {
$cos: 0;
$angle: rad($angle);
// Iterate a bunch of times.
@for $i from 0 through 10 {
$cos: $cos + pow(-1, $i) * pow($angle, 2 * $i) / fact(2 * $i);
}
@return $cos;
}
@mixin shade($type, $color: #3498db, $borderColor: #fff, $depth: 20, $angle: 135deg, $long: false, $fade: false) {
$angle: ($angle - 90);
$x: 1.1 * cos($angle) + 0px;
$y: 1.1 * sin($angle) + 0px;
$darken: (lightness($color)/$depth)/2;
$opacify: 0;
$shadow: ();
@if $long == true{
$darken:0;
}
@if $fade == true {
$opacify: (opacity($color)/$depth) ;
// added this for rendering in some browsers, remove if you like.
@include translateZ(0);
}
@for $i from 1 through $depth {
$shadow: $shadow, $i*$x $i*$y 0 hsla(hue($color) , saturation($color), (lightness($color) - ($i * $darken)), 1 - ($i * $opacify));
}
#{$type}-shadow: 1.5px 1.5px 0 $borderColor,
0px 1.5px 0 $borderColor,
-1.5px -1.5px 0 $borderColor,
-1.5px -1.5px 0 $borderColor,
-1.5px 1.5px 0 $borderColor,
1.5px -1.5px 0 $borderColor,
$shadow;
}
//mixin to provide just a basic outline for the text
@mixin outline($color: #fff) {
text-shadow: 1.5px 1.5px 0 $color,
-1.5px -1.5px 0 $color,
-1.5px -1.5px 0 $color,
-1.5px 1.5px 0 $color,
1.5px -1.5px 0 $color;
}
// Define the fonts used in the Pen
@import url(https://fonts.googleapis.com/css?family=Francois+One);
@import url(https://fonts.googleapis.com/css?family=PT+Sans);
// Define the colors
$pink : #f89bb4;
$pinkPastel : #ebaca5;
$pinkDark : #e62915;
$pinkGrayed : #d38076;
$grayLight : #cac6c5;
$offWhite : #e7e7e7;
* {
box-sizing: border-box;
}
body {
font-size: 62.5%;
}
//basic header styles
h1, h2, h3 {
font-family: 'PT Sans', sans-serif;
text-transform: uppercase;
}
h1 {
font-size: 2.4em;
background-color: rgba(41, 41, 41, 1);
text-align: center;
padding: 20px;
margin: 0;
color: #fff;
a {
display: block;
margin-top: 10px;
text-transform: none;
color: #aaa;
font-size: 16px;
text-decoration: none;
}
}
h2 {
font-size: 1.6em;
margin: 0;
padding: 10px;
border-top: 1px solid #ccc;
}
h3 {
margin: 0;
padding: 10px;
}
// Outer heading wrapper (for descriptions, not for the actual effects)
.headingOuter {
background: #f1f1f1;
text-align: center;
margin-top: 30px;
border-top: 1px solid #333;
border-bottom: 1px solid #333;
&:first-child {
margin-top: 0;
}
h1 + & {
margin-top: 10px;
}
}
.headingWrapper {
text-align: center;
background-color: #fff;
padding: 10px;
}
// default header class – used on all examples
.header {
display: inline-block;
text-align: center;
font-family: 'Francois One', Helvetica, Arial, sans-serif;
font-size: 96px;
color: $offWhite;
text-decoration: none;
@include outline($grayLight);
transition: all 400ms ease-in-out;
}
// effect for pushing the text down onto the page
// default is the letters emerging from the page and merging back down on hover
.header--pushDown {
@include shade(text, #aaa, #333, 10, 135deg, true);
&:hover {
transform: translate(9px, 9px);
@include outline($grayLight);
}
}
// raising text from page when hovered, so flipped state to header--pushDown class
.header--raiseUp {
&:hover {
transform: translate(-9px, -9px);
@include shade(text, #aaa, #333, 10, 135deg, true);
}
}
// creates a shadow effect, rather than a raised lettering effect
// simply by adjusting the translate position a little
.header--shadow {
&:hover {
transform: translate(5px, 0);
}
&.header--raiseUp {
&:hover {
transform: translate(-5px, 0);
}
}
}
//Brighter colored text
.color-bright {
background-color: $pinkPastel;
& .header {
color: $pink;
@include outline($pinkGrayed);
}
//push down text
& .header--pushDown {
@include shade(text, $pinkDark, #fff, 10, 135deg, true);
&:hover {
@include outline($pinkGrayed);
}
}
//raise up text
& .header--raiseUp:hover {
@include shade(text, $pinkDark, #fff, 10, 135deg, true);
}
}
// SVG Pattern text effect
// Same as the above but with a pattern text effect on hover
// Played around with this for a while – cannot be done with background clip and a CSS gradient as the
// text-shadow always appears in front of the background (unless you have no background color on the wrapping element)
// Therefore, use SVG linearGradient and animate the stop points using CSS
svg {
line-height: 1.2;
width: 410px;
height: 1.5em;
}
.header--svg {
text,
stop {
transition: all 350ms ease-in-out;
}
text {
text-transform: uppercase;
fill: url(#striped);
@include outline($grayLight);
}
&:hover text {
@include shade(text, #aaa, #333, 10, 135deg, true);
}
//animate gradient stop points
& stop {
stop-color: $offWhite;
}
&:hover stop {
stop-color: #fff;
&:nth-child(2),
&:nth-child(3) {
stop-color: $pinkGrayed;
}
}
}
// Brighter version of the SVG pattern text
.color-bright {
& .header--svg {
text {
fill: url(#stripedColor);
@include outline($pinkGrayed);
}
&:hover text {
@include shade(text, $pinkDark, #fff, 10, 135deg, true);
}
}
& stop {
stop-color: $pink;
}
& .header--svg:hover stop {
&:nth-child(2),
&:nth-child(3) {
stop-color: #ed5751;
}
}
}
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.