惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
大猫的无限游戏
大猫的无限游戏
Hugging Face - Blog
Hugging Face - Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Vercel News
Vercel News
人人都是产品经理
人人都是产品经理
G
Google Developers Blog
WordPress大学
WordPress大学
S
SegmentFault 最新的问题
雷峰网
雷峰网
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Jina AI
Jina AI
博客园 - 叶小钗
D
DataBreaches.Net
D
Docker
月光博客
月光博客
博客园 - 司徒正美
Last Week in AI
Last Week in AI
有赞技术团队
有赞技术团队
腾讯CDC
酷 壳 – CoolShell
酷 壳 – CoolShell

CloudCannon Blog

Building with AI: Git-based vs headless vs traditional CMS CloudCannon + Astro: performance meets powerful content management Introducing the Astro Component Starter Introducing Jetstream — built on the Astro Component Starter Why we switched to the system font stack Redesigning CloudCannon’s docs with Diátaxis, Lume, and Pagefind Make content editing more visual: upgraded Editable Regions How Configuration Mode makes building editing interfaces easy Your hosting just got an upgrade (and a price cut) Custom testing domains for professional branding Keep your content consistent with input validation Managing multilingual content in CloudCannon Simplify team publishing with conflict resolution and domain tools Open Beta: Publishing Conflict Resolution Getting started with CloudCannon and Astro: Bookshop, components, and live editing Welcome to the CloudCannon Community! Omnichannel delivery is just marketing spin from API-based CMS companies Getting started with CloudCannon and Astro: Snippets and Collections Managing digital assets in CloudCannon: a guide to smart asset storage Understanding CloudCannon's branching workflows and Projects: a complete guide What is a static website? CloudCannon’s 2024 wrapped Getting started with CloudCannon and Astro: WYSIWYG blogging Jamstack vs. WordPress: reasons to make the change The top five static site generators for 2025 (and when to use them!) Free Jekyll themes for 2025: ten great community options Eleventy (11ty) vs. Hugo How to set up WYSIWYG editing with MkDocs Material The rise of static-first websites: why major brands are making the switch Watching your Core Web Vitals on Jamstack
How to create a super simple Christmas landing page
2014-12-23 · via CloudCannon Blog

This week I felt like doing something Christmas related, it seemed quite relevant. Instead of enjoying the summer sun that a New Zealand Christmas offers I decided to build an experimental landing page to share. Hope you enjoy it.

What is it? Direct link to this section

We wanted a neat way to send our users a present for the holiday season. The obvious way to give a present is in a box that they can open. Who opens presents in a 2D space? Maybe Mario but I don't think he's one of our users. Here is my Christmas Landing equipped with a 3D present fully animated.

Let's break it down.

The Layout Direct link to this section

The new version of Skeleton responsive boilerplate came out recently so I decided to use that. It gives a base which doesn't get in the way and it is basically a better browser default. This allows me to extend it really easily, pairing their grid system with our repeatable regions means I can set up the layout and hand it off. Check it out, I highly recommend it.

The Snow Background Direct link to this section

The Snow background adds a really nice effect. It uses a set of background images paired with CSS animations to make them move separately from one another. A full tutorial is available on designmodo.com.

@keyframes snow {
0% {
background-position: 0px 0px;
}
100% {
background-position: 500px 1000px, 400px 400px, 300px 300px;
}
}

body {
background-color: #eee;
background-image: url('snow.png'), url('snow2.png'), url('snow3.png');

animation: snow 20s linear infinite;
}

The Box Direct link to this section

The Box uses 3D transformations to align all the edges. I originally based the code off a tutorial found by googling "CSS Cube". It goes in depth about the 3D transformations. One very important attribute to note is transform-style: preserve-3d;, this tells the browser to act in a 3D space. If your transforms and transitions are looking very flat then this is probably what is missing. FYI, colours used are from the Google Material Design colour pallete.

<section class="cube-wrapper">
<div class="cube">
<figure class="front"></figure>
<figure class="back"></figure>
<figure class="right"></figure>
<figure class="left"></figure>
<figure class="top"></figure>
<figure class="bottom"></figure>
<figure class="shadow"></figure>
</div>
</section>

This box will live in two states, 'open' and 'closed'. I want the difference between the states to be a single class on the parent element. This way I can toggle between the states with just:

$(".cube-wrapper").click(function () {
$(this).toggleClass("open");
});

The closed state has 4 segments on the top all pointed inwards. This is just four divs occupying the four different quadrants of the parent square. I did it this way instead of adding more parent figures to keep things modular.

<figure class="top">
<div class="lower lower-left"></div>
<div class="lower lower-right"></div>
<div class="upper upper-left"></div>
<div class="upper upper-right"></div>
</figure>
.cube .top div {
width: 50%;
height: 100%;
position: absolute;

font-size: 60px;
transform-origin: left center;

border: 1px solid #3E2723;
box-sizing: border-box;
}

.cube .top .lower {
height: 50%;
width: 100%;
line-height: 96px;
}

.open .cube .top .lower {
z-index: 2;
}

.cube .top .upper-right {
transform-origin: right center;
transform: translateZ(0px) translateX(98px);
background: #795548;
}

.cube .top .lower-right {
transform-origin: bottom center;
transform: translateZ(-1px) translateY(98px);
background: #8D6E63;
}

.cube .top .upper-left {
transform-origin: left center;
transform: translateZ(0px);
background: #8D6E63;
}

.cube .top .lower-left {
transform-origin: top center;
transform: translateZ(-1px);
background: #795548;
}

This CSS places the 4 flaps in the correct position using transforms. The Z translations are very important here. The upper flaps need to be 1px above the others to prevent any overlapping effects. Another important part are the transform origins, these say where the animations should originate from.

For the open state we want the elements to flip across from the outside edge which is where we have set the transform origin.

.open .cube .top .upper-right {
transform: translateZ(-1px) translateX(98px) rotateY(150deg);
background: #795548;
}

.open .cube .top .lower-right {
transform: translateZ(-1px) translateY(98px) rotateX(-150deg);
background: #A1887F;
}

.open .cube .top .upper-left {
transform: translateZ(-1px) rotateY(-150deg);
background: #A1887F;
}

.open .cube .top .lower-left {
transform: translateZ(-1px) rotateX(150deg);
background: #795548;
}

We have translated the elements to be all on the same Z plane. I chose 150 degrees very intentionally, if it gets too close to 180 degrees the browser can't decide which way to rotate the flaps. The inverse rotation through the box didn't look that realistic so I decided to use 150 degrees.

A Shadow to top it all off Direct link to this section

Quite a simple effect gives the whole scene a lot more depth. I replicated the bottom edge of the box, extended it and changed the background.

.cube .shadow {
transform: rotateX(-90deg) translateZ(101px) translateX(0);
width: 355px;
background: rgba(0,0,0,0.1);
border: 0;
padding: 2px;
}

.open .cube .shadow {
transform: rotateX(-90deg) translateZ(101px) translateX(100px);
}

The Animations Direct link to this section

This is where a great looking box comes alive. Everything to this point has been built using transforms and a single class change. This means that all the hard work has been done and we can just roll over some CSS transitions.

First we want to add the transitions to the original state. This will allow us to synchronise the different parts when the box is closing.

.cube {
transition: transform 1s ease 0,
background 1s ease 0;
}

.cube .top div,
.cube .shadow
{
transition: transform 1s ease 1s,
background 1s ease 1s;
}

.cube .top .lower {
transition: transform 1s ease 0,
background 1s ease 0,
z-index 0 ease 0;
}

Second we want to add the transitions to the .open state. This will allow us to synchronise the different parts when the box is opening.

.open .cube {
transition: transform 1s ease 2s,
background 1s ease 2s;
}

.open .cube .top div,
.open .cube .shadow
{
transition: transform 1s ease 0s,
background 1s ease 0s;
}

.open .cube .top .lower {
transition: transform 1s ease 1s,
background 1s ease 1s,
z-index 0 ease 1s;
}

You can try these out by clicking any box on this page.

All Together Again Direct link to this section

Why would I ever use this? Direct link to this section

This shows just how much you can achieve with CSS; 3D transformations, animations and handy boilerplates lets you get a lot done in a very short amount of time. Also it's Christmas, and who doesn't like to give out presents.

That's it Direct link to this section

This landing page was a great afternoon project, plugging together a whole lot of different tutorials into a really useful resource. If you like it feel free to contribute to the GitHub Repository. I'd love to add some other branches with different holidays. If you have any questions or want to spread some cheer be sure to comment below. Merry Christmas.