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>