document.querySelector( 'style' ).innerHTML += `
hr:nth-of-type( 1 ) {
transform: translateZ( calc( var( --mid ) * 1rem ) );
}
hr:nth-of-type( 2 ) {
transform: translateZ( calc( var( --mid ) * -1rem ) );
}
hr:nth-of-type( 3 ) {
transform: rotateY( 90deg ) translateZ( calc( var( --mid ) * 1rem ) );
}
.rotate_y, .rotate_x, hr {
animation-name: rotateY;
animation-duration: 8s;
animation-delay: 0s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes rotateY {
0% {
transform: rotateY( 0deg );
}
100% {
transform: rotateY( 360deg );
}
}
.rotate_x {
animation-name: rotateX;
}
@keyframes rotateX {
0% { transform: rotateX( 0deg ); }
100% { transform: rotateX( 360deg ); }
}
`
:root {
--long: 6;
--mid: calc( var( --long ) / 2 );
}
* {
box-sizing: border-box; transform-style: preserve-3d;
margin: 0rem; padding: 0rem;
}
html, body { height: 100%; }
body, section, div, span {
display: flex;
justify-content: center; align-items: center;
}
body {
perspective: calc( var( --long ) * 3rem )
}
span:nth-of-type( 2 ) {
transform: rotateY( 180deg ) rotateX( calc( 90deg ) );
}
span:nth-of-type( 2 ) hr {
box-shadow: 0rem 0rem 0rem 0.25rem #000 inset;
}
section, hr {
position: absolute;
box-shadow: 0rem 0rem 0rem 0.25rem #444 inset;
border-style: none;
width: calc( var( --long ) * 1rem ); height: calc( var( --long ) * 1rem );
background-color: rgba( 200, 200, 200, 0.9 );
}
section {
box-shadow: 0rem 0rem 0rem 0rem transparent;
background-color: transparent;
}
<style>
hr {
animation-name: brightness;
animation-duration: 4s;
animation-timing-function: ease-in-out;
animation-direction: alternate;
}
span:nth-of-type( 1 ) hr:nth-of-type( 1 ) {
animation-delay: 2s;
}
span:nth-of-type( 1 ) hr:nth-of-type( 2 ) {
animation-delay: 3s;
}
span:nth-of-type( 1 ) hr:nth-of-type( 3 ),
span:nth-of-type( 2 ) hr:nth-of-type( 3 ) {
animation-delay: 2s;
}
span:nth-of-type( 2 ) hr:nth-of-type( 1 ),
span:nth-of-type( 2 ) hr:nth-of-type( 2 ) {
animation-delay: 1s;
}
@keyframes brightness {
0% { filter: brightness( 110% ); }
50% { filter: brightness( 50% ); }
100% { filter: brightness( 110% ); }
}
hr{ filter: blur( 0.5rem ); }
</style>
<section class='rotate_x'>
<div class='rotate_y'>
<span> <hr><hr><hr> </span> <span> <hr><hr><hr> </span>
</div>
</section>
In chrome this cube starts off blurred then quickly reverts back to it's appearance before blur; ignoring this line:
hr{ filter: blur( 0.5rem ); }
Here is a gif below that demonstrates what it looks like:
The aim is to blur the faces of a 3D transformed element. How can I achieve this with Vanilla CSS?
I first attempted blurring the cube element as a whole which fully broke the illusion. Here I am trying to blur each hr
or "face" individually. Still without the desired result
You should wrap the cube in another container that doesn't has any 3D transform applied to it, let's say .cube
:
<section class='cube'>
<section class='rotate_x'>
<div class='rotate_y'>
<span> <hr><hr><hr> </span> <span> <hr><hr><hr> </span>
</div>
</section>
</section>
Then you can apply filter animation to it without any issue:
Also you need to move perspective: calc( var( --long ) * 3rem );
from body
to the .cube
element itself.
.cube{
animation: focus 3s linear both alternate;
perspective: calc( var( --long ) * 3rem );
}
@keyframes focus {
from {
filter: blur( 0.5rem );
}
to {
filter: blur( 0rem );
}
}
document.querySelector( 'style' ).innerHTML += `
hr:nth-of-type( 1 ) {
transform: translateZ( calc( var( --mid ) * 1rem ) );
}
hr:nth-of-type( 2 ) {
transform: translateZ( calc( var( --mid ) * -1rem ) );
}
hr:nth-of-type( 3 ) {
transform: rotateY( 90deg ) translateZ( calc( var( --mid ) * 1rem ) );
}
.rotate_y, .rotate_x, hr {
animation-name: rotateY;
animation-duration: 8s;
animation-delay: 0s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes rotateY {
0% {
transform: rotateY( 0deg );
}
100% {
transform: rotateY( 360deg );
}
}
.rotate_x {
animation-name: rotateX;
}
@keyframes rotateX {
0% { transform: rotateX( 0deg ); }
100% { transform: rotateX( 360deg ); }
}
`
:root {
--long: 6;
--mid: calc( var( --long ) / 2 );
}
* {
box-sizing: border-box; transform-style: preserve-3d;
margin: 0rem; padding: 0rem;
}
html, body { height: 100%; }
body, section, div, span {
display: flex;
justify-content: center; align-items: center;
}
span:nth-of-type( 2 ) {
transform: rotateY( 180deg ) rotateX( calc( 90deg ) );
}
span:nth-of-type( 2 ) hr {
box-shadow: 0rem 0rem 0rem 0.25rem #000 inset;
}
section, hr {
position: absolute;
box-shadow: 0rem 0rem 0rem 0.25rem #444 inset;
border-style: none;
width: calc( var( --long ) * 1rem ); height: calc( var( --long ) * 1rem );
background-color: rgba( 200, 200, 200, 0.9 );
}
section {
box-shadow: 0rem 0rem 0rem 0rem transparent;
background-color: transparent;
}
.cube{
animation: focus 3s linear both alternate;
perspective: calc( var( --long ) * 3rem );
}
@keyframes focus {
from {
filter: blur( 0.5rem );
}
to {
filter: blur( 0rem );
}
}
<style>
hr {
animation-name: brightness;
animation-duration: 4s;
animation-timing-function: ease-in-out;
animation-direction: alternate;
}
span:nth-of-type( 1 ) hr:nth-of-type( 1 ) {
animation-delay: 2s;
}
span:nth-of-type( 1 ) hr:nth-of-type( 2 ) {
animation-delay: 3s;
}
span:nth-of-type( 1 ) hr:nth-of-type( 3 ),
span:nth-of-type( 2 ) hr:nth-of-type( 3 ) {
animation-delay: 2s;
}
span:nth-of-type( 2 ) hr:nth-of-type( 1 ),
span:nth-of-type( 2 ) hr:nth-of-type( 2 ) {
animation-delay: 1s;
}
@keyframes brightness {
0% { filter: brightness( 110% ); }
50% { filter: brightness( 50% ); }
100% { filter: brightness( 110% ); }
}
</style>
<section class='cube'>
<section class='rotate_x'>
<div class='rotate_y'>
<span> <hr><hr><hr> </span> <span> <hr><hr><hr> </span>
</div>
</section>
</section>