15 Pure CSS Loading Animations
House Unlock
A closed-front-door loader for property sites. The window stays dark while the key turns; once "loaded" (the .ready class is added), the window glows warm gold and the door opens to reveal a softly-lit room. Ideal as a real-estate page-load cover.
House Unlock the 1st of 15 designs in the 15 Pure CSS Loading Animations collection. The design pairs CSS styling with a small amount of JavaScript for interactivity. Copy the HTML, CSS and JavaScript panels below into your project — the JS is self-contained, has zero dependencies, and is safe to drop into any framework (React, Vue, Svelte, plain HTML). The design honours prefers-reduced-motion and uses real semantic markup, so it ships accessibility-ready out of the box.
Live preview
The code
<div class="hu-stage">
<figure class="hu-house" aria-label="Loading your home tour">
<span class="hu-roof"></span>
<span class="hu-body">
<span class="hu-window">
<span class="hu-window-glass"></span>
</span>
<span class="hu-door">
<span class="hu-door-handle"></span>
<span class="hu-key">
<span class="hu-key-bow"></span>
<span class="hu-key-shaft"></span>
<span class="hu-key-teeth"></span>
</span>
</span>
<span class="hu-floor"></span>
</span>
<figcaption class="hu-caption">Unlocking your tour…</figcaption>
</figure>
</div> .hu-stage {
display: grid;
place-items: center;
padding: 24px;
background:
radial-gradient(60% 60% at 50% 100%, rgba(212, 175, 55, 0.1) 0%, transparent 70%),
linear-gradient(180deg, #14132b 0%, #0b0b1a 100%);
border-radius: 16px;
width: 220px;
height: 220px;
}
.hu-house {
position: relative;
width: 132px;
height: 152px;
margin: 0;
padding: 0;
font-family: system-ui, sans-serif;
}
.hu-roof {
position: absolute;
top: 0;
left: 50%;
width: 0;
height: 0;
border: 30px solid transparent;
border-bottom-color: #d4af37;
transform: translateX(-50%);
filter: drop-shadow(0 4px 10px rgba(212, 175, 55, 0.25));
}
.hu-body {
position: absolute;
top: 56px;
left: 6px;
width: 120px;
height: 86px;
background: linear-gradient(180deg, #f5f0e6 0%, #e8e0d0 100%);
border-radius: 4px 4px 6px 6px;
box-shadow: 0 12px 28px -12px rgba(0, 0, 0, 0.55);
overflow: hidden;
}
.hu-floor {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 6px;
background: #2a1f1a;
}
.hu-window {
position: absolute;
top: 14px;
left: 14px;
width: 36px;
height: 28px;
border: 2px solid #d4af37;
border-radius: 3px;
background: #0a0a14;
overflow: hidden;
transition:
background 0.6s ease,
box-shadow 0.6s ease;
}
.hu-window::before,
.hu-window::after {
content: "";
position: absolute;
background: #d4af37;
}
.hu-window::before {
top: 0;
bottom: 0;
left: 50%;
width: 1.5px;
transform: translateX(-50%);
}
.hu-window::after {
left: 0;
right: 0;
top: 50%;
height: 1.5px;
transform: translateY(-50%);
}
.hu-window-glass {
position: absolute;
inset: 0;
background: radial-gradient(circle at 50% 70%, #ffd479 0%, #d4af37 50%, transparent 75%);
opacity: 0;
transform: scale(0.7);
transition:
opacity 0.7s ease,
transform 0.7s ease;
}
.hu-door {
position: absolute;
bottom: 6px;
left: 50%;
width: 38px;
height: 60px;
margin-left: -19px;
background: linear-gradient(180deg, #6b3f2a 0%, #4a2d1f 100%);
border-radius: 5px 5px 0 0;
border: 1px solid rgba(0, 0, 0, 0.4);
transform-origin: left center;
transform: rotateY(0deg);
transition: transform 0.85s cubic-bezier(0.5, 0, 0.3, 1.2);
box-shadow: inset -2px 0 0 rgba(255, 255, 255, 0.04);
}
.hu-door-handle {
position: absolute;
right: 5px;
top: 50%;
width: 5px;
height: 5px;
margin-top: -2.5px;
background: #d4af37;
border-radius: 50%;
box-shadow: 0 0 6px rgba(212, 175, 55, 0.55);
}
.hu-key {
position: absolute;
right: 10px;
top: 50%;
width: 22px;
height: 8px;
margin-top: -4px;
transform-origin: 18px center;
animation: huKeyTurn 2.4s cubic-bezier(0.5, 0, 0.3, 1.2) infinite;
}
.hu-key-bow {
position: absolute;
left: 0;
top: -3px;
width: 14px;
height: 14px;
border: 2px solid #d4af37;
border-radius: 50%;
background: rgba(212, 175, 55, 0.12);
box-shadow: 0 0 8px rgba(212, 175, 55, 0.35);
}
.hu-key-shaft {
position: absolute;
left: 12px;
top: 50%;
width: 9px;
height: 2px;
margin-top: -1px;
background: #d4af37;
border-radius: 1px;
}
.hu-key-teeth {
position: absolute;
right: 0;
top: 50%;
width: 4px;
height: 4px;
margin-top: -2px;
background: #d4af37;
border-radius: 0 1px 1px 0;
box-shadow: -3px 2px 0 0 #d4af37;
}
.hu-caption {
position: absolute;
left: 50%;
bottom: -28px;
transform: translateX(-50%);
font-size: 11px;
letter-spacing: 0.14em;
text-transform: uppercase;
font-weight: 600;
color: #d4af37;
white-space: nowrap;
animation: huCaption 2.4s ease-in-out infinite;
}
.hu-house.ready .hu-window {
background: #ffd479;
box-shadow:
0 0 14px rgba(255, 212, 121, 0.55),
inset 0 0 12px rgba(255, 212, 121, 0.4);
}
.hu-house.ready .hu-window-glass {
opacity: 1;
transform: scale(1);
}
.hu-house.ready .hu-door {
transform: rotateY(-72deg);
}
.hu-house.ready .hu-key,
.hu-house.ready .hu-caption {
display: none;
}
@keyframes huKeyTurn {
0%,
18% {
transform: rotate(0deg) translateX(0) scale(1);
opacity: 0;
}
10% {
opacity: 1;
}
35%,
60% {
transform: rotate(90deg) translateX(0) scale(1);
opacity: 1;
}
78% {
transform: rotate(90deg) translateX(-6px) scale(0.6);
opacity: 0;
}
100% {
transform: rotate(0deg) translateX(0) scale(1);
opacity: 0;
}
}
@keyframes huCaption {
0%,
100% {
opacity: 0.55;
}
50% {
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.hu-stage,
.hu-stage * {
animation: none !important;
}
}
// Drives the door-open reveal. Replace with your real "page loaded" trigger.
document.querySelectorAll(".hu-house").forEach(function (house) {
var ready = false;
function tick() {
ready = !ready;
house.classList.toggle("ready", ready);
setTimeout(tick, ready ? 1800 : 3200);
}
setTimeout(tick, 3200);
});