- const URL = "https://css-tricks.com"
//- Front
//- Back
//- Right
//- Left
//- Top
//- Bottom
mixin cuboid(className)
.cuboid(class=className)
- let s = 0
while s < 6
.cuboid__side
- s++
.scene__wrapper
.scene
//- Plane that all the 3D stuff sits on
.plane
.studio
+cuboid('floor')
+cuboid('rug')
+cuboid('wall wall--left')
.window
+cuboid('window__frame window__frame--top')
+cuboid('window__frame window__frame--left')
+cuboid('window__frame window__frame--right')
+cuboid('window__frame window__frame--bottom')
+cuboid('window__frame window__frame--middle')
+cuboid('wall wall--right-left')
+cuboid('wall wall--right-upper')
+cuboid('wall wall--right-right')
+cuboid('skirting skirting--left')
+cuboid('skirting skirting--right')
+cuboid('windowsill')
+cuboid('wall wall--right-lower')
+cuboid('bear-canvas')
+cuboid('jfdi')
View Compiled
*
box-sizing border-box
transform-style preserve-3d
:root
--blur 1vmin
--perspective 2000
--rotate-x -20
--rotate-y -45
--plane-height 50
--plane-width 50
--dark 0
--zoomed 0
--scale calc(0.75 + (var(--zoomed) * 4))
--wall-thickness 4
--cm calc((var(--plane-height) / 240))
--transition 0.2s
// Colors
--floor-shade-one hsl(30, 40%, 40%)
--floor-shade-two hsl(30, 40%, 60%)
--floor-shade-three hsl(30, 40%, 80%)
--windowsill-shade-one hsl(35, 50%, 50%)
--windowsill-shade-two hsl(35, 50%, 40%)
--windowsill-shade-three hsl(35, 50%, 30%)
--wall-shade-one hsl(0, 0%, 98%)
--wall-shade-two hsl(0, 0%, 95%)
--wall-shade-three hsl(0, 0%, 90%)
--wall-shade-four hsl(0, 0%, 85%)
--skirting-one hsl(0, 0%, 93%)
--skirting-two hsl(0, 0%, 88%)
--fade-one hsl(0, 80%, 85%)
--fade-two hsl(200, 80%, 85%)
--fade-three hsl(280, 80%, 85%)
--fade-four hsl(120, 80%, 85%)
--cube hsl(0, 0%, 95%)
--leg-one hsl(0, 0%, 10%)
--leg-two hsl(0, 0%, 12%)
--leg-three hsl(0, 0%, 14%)
--leg-four hsl(0, 0%, 16%)
--rug hsl(210, 40%, 10%)
--peripheral-one hsl(0, 0%, 20%)
--peripheral-two hsl(0, 0%, 30%)
--peripheral-three hsl(0, 0%, 40%)
--peripheral-four hsl(0, 0%, 50%)
--mac-one hsl(0, 0%, 80%)
--mac-two hsl(0, 0%, 70%)
--blind hsl(30, 50%, 90%)
--mac-three hsl(0, 0%, 60%)
--pot-one hsl(20, 50%, 50%)
--pot-two hsl(20, 50%, 40%)
--pot-three hsl(20, 50%, 30%)
--chair-one hsl(0, 0%, 0%)
--chair-two hsl(0, 0%, 10%)
--chair-three hsl(0, 0%, 20%)
--chair-four hsl(0, 0%, 30%)
--chair-accent-one hsl(0, 0%, 95%)
--chair-accent-two hsl(0, 60%, 60%)
--bg hsl(210, 80%, 90%)
--light hsl(0, 0%, 80%)
--icon hsl(210, 50%, 60%)
// We're saying that 50vmin === 240cm
audio
display none
body
min-height 100vh
overflow hidden
.dg.ac
z-index 100
transform translate3d(0, 0, 50vmin)
.scene
perspective calc(var(--perspective, 800) * 1px)
transform-style preserve-3d
height 100vh
width 100vw
display flex
align-items center
justify-content center
transform scale(var(--scale)) translate3d(0, 0, 50vmin)
&__wrapper
transition background var(--transition)
background var(--bg)
.plane
height calc(var(--plane-height, 25) * 1vmin)
width calc(var(--plane-width, 25) * 1vmin)
transform-style preserve-3d
transform rotateX(calc((var(--rotate-x, -24) - (var(--zoomed) * var(--rotate-x, -24))) * 1deg)) rotateY(calc(((var(--rotate-y, -24) - (var(--zoomed) * var(--rotate-y, -24))) + (var(--zoomed) * -90)) * 1deg)) rotateX(90deg) translate3d(0, 0, 0)
&:before
content ''
background hsla(0, 0%, 0%, 0.5)
filter blur(var(--blur))
height 112%
width 112%
position absolute
top -8%
left -10%
transform translate3d(0, 0, -11vmin)
z-index -1
// This is what makes the CSS variable powered cuboid
.cuboid
--width var(--cuboid-width, 15)
--height var(--cuboid-height, 10)
--depth var(--cuboid-depth, 4)
height calc(var(--depth) * 1vmin)
width calc(var(--width) * 1vmin)
position absolute
transform rotateZ(calc(var(--starting-rotation, 0) * 1deg)) translate3d(calc(var(--x, 0) * 1vmin), calc(var(--y, 0) * 1vmin), calc(var(--z, 0) * 1vmin)) rotateX(calc(var(--rotate-cuboid-x, 0) * 1deg)) rotateY(calc(var(--rotate-cuboid-y, 0) * 1deg)) rotateZ(calc(var(--rotate-cuboid-z, 0) * 1deg))
transform-style preserve-3d
&__side
transform-style preserve-3d
& > div:nth-of-type(1)
height calc(var(--height) * 1vmin)
width 100%
transform-origin 50% 50%
position absolute
top 50%
left 50%
transform translate(-50%, -50%) rotateX(-90deg) translate3d(0, 0, calc((var(--depth) / 2) * 1vmin))
& > div:nth-of-type(2)
height calc(var(--height) * 1vmin)
width 100%
transform-origin 50% 50%
transform translate(-50%, -50%) rotateX(-90deg) rotateY(180deg) translate3d(0, 0, calc((var(--depth) / 2) * 1vmin))
position absolute
top 50%
left 50%
& > div:nth-of-type(3)
height calc(var(--height) * 1vmin)
width calc(var(--depth) * 1vmin)
transform translate(-50%, -50%) rotateX(-90deg) rotateY(90deg) translate3d(0, 0, calc((var(--width) / 2) * 1vmin))
position absolute
top 50%
left 50%
& > div:nth-of-type(4)
height calc(var(--height) * 1vmin)
width calc(var(--depth) * 1vmin)
transform translate(-50%, -50%) rotateX(-90deg) rotateY(-90deg) translate3d(0, 0, calc((var(--width) / 2) * 1vmin))
position absolute
top 50%
left 50%
& > div:nth-of-type(5)
height calc(var(--depth) * 1vmin)
width calc(var(--width) * 1vmin)
transform translate(-50%, -50%) translate3d(0, 0, calc((var(--height) / 2) * 1vmin))
position absolute
top 50%
left 50%
& > div:nth-of-type(6)
height calc(var(--depth) * 1vmin)
width calc(var(--width) * 1vmin)
transform translate(-50%, -50%) translate3d(0, 0, calc((var(--height) / 2) * -1vmin)) rotateX(180deg)
position absolute
top 50%
left 50%
.studio
height 100%
width 100%
transform translate3d(0, 0, calc((-10 + (var(--zoomed) * -10)) * 1vmin))
.floor
--height 1
--width calc(50 + var(--wall-thickness))
--depth calc(50 + var(--wall-thickness))
--z -0.5
--y calc(var(--wall-thickness) * -1)
--x calc(var(--wall-thickness) * -1)
transition background var(--transition)
div:not(.studio__shadow)
background var(--floor-shade-three)
div:nth-of-type(1)
background var(--floor-shade-one)
div:nth-of-type(3)
background var(--floor-shade-two)
div:nth-of-type(5)
transition filter var(--transition)
filter brightness(1)
&:after
content ''
position absolute
top 0
left 0
height 100%
width 100%
transform rotate(90deg)
background url('https://images.pexels.com/photos/235994/pexels-photo-235994.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260') 0 0 / 15vmin 15vmin
.wall
transition background var(--transition)
&--left
--height calc(220 * var(--cm))
--width var(--wall-thickness)
--depth calc((240 * var(--cm)) + var(--wall-thickness))
--z calc(110 * var(--cm))
--x calc(var(--wall-thickness) * -1)
--y calc(var(--wall-thickness) * -1)
div
&:nth-of-type(1)
background var(--wall-shade-four)
&:nth-of-type(2)
background var(--wall-shade-one)
&:nth-of-type(3)
background var(--wall-shade-one)
overflow hidden
&:nth-of-type(5)
background var(--wall-shade-three)
&:nth-of-type(4)
&:nth-of-type(6)
background var(--wall-shade-two)
&--right-lower
--height calc(100 * var(--cm))
--width 50
--depth var(--wall-thickness)
--z calc(50 * var(--cm))
--y calc(var(--wall-thickness) * -1)
&:after
content ''
height 30%
width calc((114 * var(--cm)) * 1vmin)
top 102%
left calc((22 * var(--cm)) * 1vmin)
filter blur(calc(0.75 * var(--blur)))
background hsla(0, 0%, 0%, 0.5)
position absolute
transform-origin 50% 0
transform rotateX(90deg) translate(0, calc((44 * var(--cm)) * 1vmin))
div
background var(--wall-shade-four)
&:nth-of-type(5)
background var(--wall-shade-three)
&:nth-of-type(2)
&:nth-of-type(3)
background var(--wall-shade-one)
&--right-left
--height calc(220 * var(--cm))
--width calc(22 * var(--cm))
--depth var(--wall-thickness)
--z calc(110 * var(--cm))
--y calc(var(--wall-thickness) * -1)
div
background var(--wall-shade-four)
&:nth-of-type(3)
background var(--wall-shade-two)
&:nth-of-type(2)
background var(--wall-shade-one)
&--right-upper
--height calc(22 * var(--cm))
--width calc(240 * var(--cm))
--depth var(--wall-thickness)
--z calc(209 * var(--cm))
--y calc(var(--wall-thickness) * -1)
div
background var(--wall-shade-four)
&:nth-of-type(2)
&:nth-of-type(3)
background var(--wall-shade-one)
&:nth-of-type(5)
background var(--wall-shade-three)
&--right-right
--height calc(220 * var(--cm))
--width calc((240 - 136) * var(--cm))
--depth var(--wall-thickness)
--z calc(110 * var(--cm))
--y calc(var(--wall-thickness) * -1)
--x calc(136 * var(--cm))
div
background var(--wall-shade-four)
&:nth-of-type(1):after
content ''
position absolute
height 24%
width 70%
border-radius 50%
background none
filter blur(calc(2 * var(--blur)))
top 15%
left 15%
opacity 0.75
&:nth-of-type(2)
&:nth-of-type(3)
background var(--wall-shade-one)
&:nth-of-type(4)
background var(--wall-shade-four)
&:nth-of-type(5)
background var(--wall-shade-three)
.windowsill
--height calc(2 * var(--cm))
--depth calc(22 * var(--cm))
--width calc(114 * var(--cm))
--z calc(100 * var(--cm) )
--x calc(22 * var(--cm))
--y calc(var(--wall-thickness) * -0.8)
div
background var(--windowsill-shade-one)
&:nth-of-type(1)
transition filter var(--transition)
filter brightness(0.5)
background url("https://images.pexels.com/photos/172276/pexels-photo-172276.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500")
&:nth-of-type(2)
background var(--wall-shade-one)
&:nth-of-type(5)
transition filter var(--transition)
background url("https://images.pexels.com/photos/172276/pexels-photo-172276.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500")
&:nth-of-type(6)
background var(--windowsill-shade-three)
.skirting
&--left
--height calc(8 * var(--cm))
--width calc(2 * var(--cm))
--depth calc(240 * var(--cm))
--z calc(4 * var(--cm))
div
background var(--skirting-one)
&:nth-of-type(3)
background var(--skirting-one)
&:nth-of-type(5)
background var(--skirting-one)
&--right
--height calc(8 * var(--cm))
--width calc(240 * var(--cm))
--depth calc(2 * var(--cm))
--z calc(4 * var(--cm))
div
background var(--skirting-two)
.rug
--height calc(1 * var(--cm))
--width calc(140 * var(--cm))
--depth calc(140 * var(--cm))
--x calc(80 * var(--cm))
--y calc(50 * var(--cm))
--z calc(0.5 * var(--cm))
div
background var(--rug)
&:nth-of-type(5)
transition filter var(--transition)
filter brightness(1)
background url('https://images.pexels.com/photos/3707669/pexels-photo-3707669.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940')
background-size cover
.bear-canvas
--width calc(60 * var(--cm))
--height calc(60 * var(--cm))
--depth calc(2 * var(--cm))
--z calc(80 * var(--cm))
--x calc(168 * var(--cm))
--y var(--cm)
div
background hsl(0, 0%, 95%)
filter brightness(1)
transition filter var(--transition)
&:nth-of-type(1)
background linear-gradient(hsla(0, 0%, 100%, 0.25), hsla(0, 0%, 100%, 0.25)), url("https://assets.codepen.io/605876/avatar.png"), hsl(0, 0%, 98%)
background-size 75%
background-position center
background-repeat no-repeat
filter brightness(1) grayscale(1)
&:nth-of-type(2):after
content ''
height 100%
width 100%
background hsla(0, 0%, 0%, 0.5)
filter blur(var(--blur))
position absolute
top 10%
left -5%
.window
width calc((114 * var(--cm)) * 1vmin)
background linear-gradient(40deg, transparent 20%, hsla(0, 0%, 100%, 0.5), transparent 50%), linear-gradient(40deg, transparent 50%, hsla(0, 0%, 100%, 0.25), transparent 60%), hsla(190, 80%, 90%, 0.25)
height calc((95 * var(--cm)) * 1vmin)
position absolute
transform rotateX(90deg) translate3d(calc((22 * var(--cm)) * 1vmin), calc((102 * var(--cm)) * 1vmin), calc((18 * var(--cm)) * 1vmin))
transform-origin 50% 0%
&__frame
&--top
&--middle
&--bottom
--depth calc(4 * var(--cm))
--width calc(115 * var(--cm))
--height calc(4 * var(--cm))
div
background hsl(0, 0%, 98%)
&:nth-of-type(6)
background hsl(0, 0%, 90%)
&--top
bottom 0
&--middle
top 60%
&--left
&--right
--depth calc(95 * var(--cm))
--width calc(4 * var(--cm))
--height calc(4 * var(--cm))
div
background hsl(0, 0%, 98%)
&:nth-of-type(6)
background hsl(0, 0%, 90%)
&--right
right 0
.jfdi
--height calc(40 * var(--cm))
--width calc(2 * var(--cm))
--depth calc(60 * var(--cm))
--y calc(90 * var(--cm))
--x calc(var(--hang) * var(--cm))
--z calc(190 * var(--cm))
div
background black
&:nth-of-type(4):after
content ''
background hsla(0, 0%, 0%, 0.5)
position absolute
top 8%
left 4%
height 100%
width 100%
transition transform var(--transition)
filter blur(var(--blur))
&:nth-of-type(3)
background hsl(0, 0%, 15%)
&:nth-of-type(3):after
transition color var(--transition)
content 'JFDI'
position absolute
top 0
left 0
height 100%
width 100%
color hsl(0, 0%, 100%)
font-weight bold
font-family sans-serif
font-size calc((22 * var(--cm)) * 1vmin)
text-align center
line-height calc((40 * var(--cm) * 1vmin))
View Compiled
// Purely for debugging purposes
const {
dat: { GUI },
} = window
const CONTROLLER = new GUI()
const CONFIG = {
'rotate-x': -24,
'rotate-y': -40,
hang: true,
}
const UPDATE = () => {
Object.entries(CONFIG).forEach(([key, value]) => {
document.documentElement.style.setProperty(`--${key}`, value)
})
document.documentElement.style.setProperty('--hang', CONFIG.hang ? 1 : 0)
}
const PLANE_FOLDER = CONTROLLER.addFolder('Plane')
PLANE_FOLDER.add(CONFIG, 'rotate-x', -360, 360, 1)
.name('Rotate X (deg)')
.onChange(UPDATE)
PLANE_FOLDER.add(CONFIG, 'rotate-y', -360, 360, 1)
.name('Rotate Y (deg)')
.onChange(UPDATE)
CONTROLLER.add(CONFIG, 'hang')
.name('Offset canvas')
.onChange(UPDATE)
UPDATE()
View Compiled
This Pen doesn't use any external CSS resources.