<!-- 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
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.