Search code examples
csstextshadow

CSS text shadow with perspective


I want to achieve a shadow effect where it looks like the bottom of the text is touching the floor and shadow is cast behind it. Something like the perspective box in this post or the shadows in this image

Shadows
(source: psd-dude.com)

I only need the shadow to be going in one direction.

Is there a pure CSS solution? Is there a solution at all? I've seen it done with boxes, but not text. The image above was made with Photoshop


Solution

  • You can play with CSS transforms and perspectives:

    body {
      margin: 50px;
      text-align: center;
    }
    #shadow {
      border: 1px solid blue;
      position: relative;
      font-size: 50px;
      font-weight: bold;
      text-align: center;
      perspective: 50px;
      perspective-origin: 50% 100%;
      display: inline-block;
    }
    #shadow::after {
      content: 'p Shadow q';
      outline: 1px solid red;
      position: absolute;
      top: 0; right: 0; bottom: 0; left: 0;
      transform: scaleY(0.5) rotateX(-15deg);
      transform-origin: 50% 100%;
      opacity: .3;
    }
    <div id="shadow">p Shadow q</div>

    The bottom of the shadow does not seem to completely coincide with the bottom of the text, that's because the baseline is a bit higher. Otherwise it would be bad for characters like g j p q y.

    If you don't want this space, you can reduce the line-height.

    body {
      margin: 50px;
    }
    #shadow {
      position: relative;
      font-size: 50px;
      font-weight: bold;
      text-align: center;
      line-height: 0;
      perspective: 50px;
      perspective-origin: 50% 100%;
    }
    #shadow::after {
      content: 'p Shadow q';
      position: absolute;
      top: 0; right: 0; bottom: 0; left: 0;
      transform: scaleY(0.5) rotateX(-15deg);
      transform-origin: 50% 100%;
      opacity: .3;
    }
    <div id="shadow">p Shadow q</div>

    I hard-coded the shadow text in the pseudo-element. It would be desirable to avoid this, and let it use the same text as the element. That's possible with an element() background, only supported by Firefox.

    body {
      margin: 50px;
      text-align: center;
    }
    #shadow {
      border: 1px solid blue;
      position: relative;
      font-size: 50px;
      font-weight: bold;
      text-align: center;
      perspective: 50px;
      perspective-origin: 50% 100%;
      display: inline-block;
    }
    #shadow::after {
      content: '';
      background: -moz-element(#shadow);
      background: element(#shadow);
      outline: 1px solid red;
      position: absolute;
      top: 0; right: 0; bottom: 0; left: 0;
      transform: scaleY(0.5) rotateX(-15deg);
      transform-origin: 50% 100%;
      opacity: .3;
    }
    <div id="shadow">p Shadow q</div>