2

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

0

2 Answers 2

4

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>

Sign up to request clarification or add additional context in comments.

2 Comments

Good answer ... And such a pity that the background: element() is in a dead road
Used most of your answer. Here is what you helped create: giphy gif
2

I thought about a solution where I add an :after-Element to each letter, with content: "T" for example for the letter T. Then make the content itself invisible and just use the text-shadow property on :after-Element, which we can rotate via text-transform: rotateX(70deg).

I made a draft on JSFiddle.

enter image description here

1 Comment

Hint: if there is no need to style the shadow of each letter individually you could also use only one after-element with the whole text as content.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.