使用 HTML、CSS 和 JS 创建响应式着陆页 🔥
亲爱的开发者们,大家好!今天我们将学习如何使用 HTML、CSS 和 JS,并借助 GreenSock Animation 库创建经典动画,轻松创建一个响应式落地页。
用 HTML 和 CSS 制作落地页非常简单,但你知道是什么让我们的文章更有趣吗?好吧,我们这就来聊聊……
但在此之前,您可以观看下面的视频,了解代码教程演示。
代码教程
如果您想观看更多类似的网页设计教程,请考虑订阅我们的YouTube频道!
本文的源代码已上传至 GitHub,其中包含所有图片及更多内容,请访问下方链接获取源代码。
如今,网站动画扮演着至关重要的角色,因为令人惊艳的动画能够显著提升用户体验(UX),吸引用户驻足欣赏。
在开始编写代码之前,让我们先了解一些关于 GSAP 的知识。
GSAP是什么?
你以前听说过吗?如果听说过,那你真是太棒了!如果没听说过,那就给我个机会给你解释一下!!!
GSAP 是一个 JavaScript 库,用于构建可在**所有主流浏览器上运行的高性能动画。 **它甚至可以为 CSS、SVG、Canvas、React、Vue、WebGL、颜色、字符串、运动路径、通用对象……任何 JavaScript 可以操作的对象添加动画!
GSAP 的核心是一个高速属性操作器,能够以极高的精度随时间更新属性值。它的速度比 jQuery 快 20 倍 🔥!
好啦好啦😆!那么,我们就不浪费时间了,直接来看看怎么写代码吧。
首先从我们的项目文件夹结构开始,我们基本上只需要以下 3 个文件:👇
现在使用外部库进行表示,这些外部库主要包括:
所以,在您最喜欢的代码编辑器中创建这些文件之后,让我们开始在 CSS 文件中进行一些 HTML 重置,同时也要考虑根元素。
/*===== GOOGLE FONTS =====*/
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap");
* {
margin: 0;
padding: 0;
}
/*===== ROOT ======*/
:root{
--primary-color: #1B2338;
--secondary-color:#B0253C;
--color-text: #fff;
--header-height: 3rem;
}
/*===== RESET HTML =====*/
html, body {
width: 100%;
height: 100vh;
font-family: 'Poppins',sans-serif;
font-size: 14px;
color: #fff;
overflow: hidden !important;
}
ul li{
list-style-type: none;
}
a{
text-decoration: none;
}
button{
cursor: pointer;
border: none;
outline: none;
}
所以在上面的代码中,我们从 fonts.google.com 导入了名为 Poppins 的 Google 字体👌 之后,我们设置了一些 CSS 变量并重置了我们之前使用的 HTML 元素!
现在让我们来制作稍后要用JS添加动画效果的叠加层。
HTML语法:
<div class="overlay first"></div>
<div class="overlay second"></div>
<div class="overlay third"></div>
CSS样式:
.overlay {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
height: 100%;
z-index: 100;
}
.first {
background-color: var(--primary-color);
}
.second {
background-color: white;
left: 33.3%;
}
.third {
background-color: var(--secondary-color);
left: 66.6%;
}
生成的输出:
在我们继续讲解下一个元素之前,我想总结一下,很遗憾,我们必须注释掉叠加层代码,因为它会像某种东西一样向上滑动过渡!
评论完毕后,我们接下来讨论容器和条带:
HTML语法:
<!-- ===== CONTAINER'S ===== -->
<div class="left_container"></div>
<div class="right_container"></div>
<!-- ===== STRIPS ===== -->
<div class="strips">
<div class="left_strip"></div>
<div class="right_strip"></div>
</div>
CSS样式:
/*===== CONTAINER'S =====*/
.left_container, .right_container {
position: absolute;
height: 100%;
width: 50%;
z-index: -50;
}
.left_container {
background: var(--primary-color);
}
.right_container {
left: 50%;
background: var(--secondary-color);
}
/*===== STRIPS =====*/
.left_strip, .right_strip{
position: absolute;
width: 1px;
height: 100vh;
background: #fff;
opacity: .5;
z-index: -10;
}
.left_strip {
left: 120px;
}
.right_strip {
right: 120px;
}
输出 :
各位,更重要的是,在这篇基于代码的文章中,CSS 属性 z-index 发挥了至关重要的作用。
现在让我们完成导航栏。
导航栏的 HTML 语法:
<!-- ===== NAVBAR ===== -->
<header>
<nav class="nav body_layout">
<div class="nav_insider">
<div class="logo">
<h3 class="nav__icon">levi's <sup>®</sup></h3>
</div>
<div class="nav__menu" id="nav__menu">
<ul class="nav__list">
<li class="nav__item"><a href="#" class="nav__link">man</a></li>
<li class="nav__item"><a href="#" class="nav__link">women</a></li>
<li class="nav__item"><a href="#" class="nav__link">kids</a></li>
<li class="nav__item search_btn">
<button class="search_btn">
<i class="ri-search-line"></i>
</button>
</li>
<li class="nav__item cart_btn">
<button class="cart_btn">
<i class="ri-shopping-bag-fill"></i>
</button>
</li>
</ul>
</div>
</div>
<div class="cart_btn_wrapper">
<button class="search_btn"><i class="ri-search-line"></i></button>
<button class="cart_btn"> <i class="ri-shopping-bag-fill"></i></button>
</div>
<button class="menu_toggle_btn" id="menu_toggle_btn">
<i class="ri-menu-3-fill nav__icon"></i>
</button>
</nav>
</header>
导航栏的 CSS 样式:
/*===== BODY LAYOUT =====*/
.body_layout{
display: grid;
grid-template-columns: 100%;
align-items: center;
padding-left: 0.5rem;
padding-right: 0.5rem;
}
/*===== HEADER =====*/
header{
width: 100%;
position: fixed;
top: 0;
left: 0;
}
/*===== NAV =====*/
.nav{
height: 5rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.nav_insider{
width: 75%;
display: flex;
align-items: center;
}
.nav__menu{
margin-left: 3rem;
}
.nav__item{
margin-bottom: 2rem;
}
.nav__link{
color: var(--color-text);
text-transform: capitalize;
font-size: 16px;
}
.nav__link:hover{
border-bottom: 1px solid var(--color-text);
}
.nav__icon{
font-size: 1.5rem;
text-transform: capitalize;
}
.search_btn, .cart_btn{
width: 40px;
height: 40px;
border-radius: 50px;
background-color: white;
}
.search_btn{
margin-right:88px;
}
.search_btn i, .cart_btn i{
font-size: 17px;
font-weight: 600;
}
.cart_btn i{
color: var(--secondary-color);
}
输出 :
现在,社交链接和我们的产品信息
HTML语法:
<!-- ===== SOCIAL ===== -->
<div class="social">
<ul class="social__list">
<li class="social_item"><i class="ri-facebook-fill"></i></li>
<li class="social_item"><i class="ri-instagram-fill"></i></li>
<li class="social_item"><i class="ri-twitter-fill"></i></li>
</ul>
</div>
<!-- ===== PRODUCT-IMAGE ===== -->
<img src="./img/levis.png" class="product_img" alt="product_img">
<!-- ===== PRODUCT-INFO ===== -->
<div class="product_text">
<h1 class="product_title">levi's <sup>®</sup></h1>
<p class="product_type">full sleeve t-shirt</p>
</div>
CSS样式:
/*===== SOCIAL =====*/
.social {
position: absolute;
left: -2%;
top: 50%;
transform: rotate(-90deg);
}
.social ul {
list-style: none;
}
.social ul li {
display: inline-block;
font-weight: 500;
font-size: 14px;
cursor: pointer;
}
.social ul li:nth-child(1)::after{
content: "/";
position: absolute;
left: 25%;
color: rgba(238, 238, 238, 0.726);
}
.social ul li:nth-child(2)::after{
content: "/";
position: absolute;
left: 70%;
color: rgba(238, 238, 238, 0.726);
}
.social ul li:not(:last-child) {
padding-right: 60px;
}
.social ul li i{
font-size: 19px;
}
/*===== PRODUCT-IMAGE =====*/
.product_img {
width: 444px;
max-width: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -40%);
animation: move 4s ease-in-out infinite;
z-index: -10;
}
@keyframes move {
0% {
transform: translate(-50%, -46%);
}
50% {
transform: translate(-50%, -54%);
}
100% {
transform: translate(-50%, -46%);
}
}
.product_text{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.product_title {
font-size: 100px;
text-transform: capitalize;
}
.product_title > sup{
font-size: 50px;
}
.product_type {
font-size: 25px;
font-weight: 500;
}
输出 :
现在,我们来看HTML侧的最后一个元素,也就是底部的导航栏 :
HTML语法:
<!-- ===== BOTTOM-NAV ===== -->
<div class="bottom_nav">
<div class="slide_nav_wrapper">
<button class="prev direction_btn"><i class="ri-arrow-right-s-line"></i></button>
<button class="next direction_btn"><i class="ri-arrow-left-s-line"></i></button>
</div>
<div class="dots_wrapper">
<ul class="dots">
<li class="dot"></li>
<li class="dot"></li>
<li class="dot active"></li>
<li class="dot"></li>
<li class="dot"></li>
</ul>
</div>
</div>
CSS样式:
/*===== BOTTOM-NAV =====*/
.bottom_nav{
position: absolute;
width: 100%;
height: 5rem;
bottom: 0;
display: flex;
align-items: center;
}
/*===== SLIDE-NAV-WRAPPER =====*/
.slide_nav_wrapper{
display: flex;
flex-direction: column;
position: absolute;
left: 145px;
}
.slide_nav_wrapper button{
width: 25px;
height: 25px;
border-radius: 5px;
margin: 5px 0;
background-color: transparent;
transition: all 0.5s ease;
}
.slide_nav_wrapper button i {
font-size: 20px;
font-weight: 600;
}
.slide_nav_wrapper button:nth-child(1){
color: black;
}
.slide_nav_wrapper button:nth-child(1):hover{
background-color: var(--color-text);
}
.slide_nav_wrapper button:nth-child(2){
color: var(--color-text);
}
.slide_nav_wrapper button:nth-child(2):hover{
background-color: black;
}
/*===== DOTS-WRAPPER =====*/
.dots_wrapper{
position: absolute;
right: 180px;
width: 100px;
height: 25px;
align-items: center;
justify-content: center;
}
.dots_wrapper .dots{
display: flex;
}
.dots .dot{
margin: 0 6px;
width: 7px;
height: 7px;
border-radius: 50%;
background-color: rgba(238, 238, 238, 0.762);
}
.dot.active{
width: 9px;
height: 9px;
background-color: var(--color-text);
}
结果 :
所有 CSS 媒体查询:
/*===== MEDIA QUERIES (FOR MAX-WIDTH:768px) =====*/
@media screen and (max-width:768px) {
.logo{
margin-left: 0.5rem;
}
.social{
display: none;
}
.nav{
height: 2.5rem;
}
.nav__menu{
position: fixed;
top: var(--header-height);
background-color: black;
right: -100%;
width: 44%;
height: 100vh;
padding: 1.5rem;
z-index: 25;
border-top: 1px solid #eee;
border-left: 1px solid #eee;
transition: all 0.5s;
}
.cart_btn_wrapper{
position: fixed;
top: var(--header-height);
background-color: black;
right: -100%;
padding: 1.5rem;
background-color: var(--secondary-color);
z-index: 10;
transition: 0.5s;
border-top: 1px solid var(--color-text);
border-left: 1px solid var(--color-text);
}
.menu_toggle_btn{
background-color: transparent;
color: white;
}
.cart_btn, .search_btn {
width: 25px;
height: 25px;
}
.cart_btn i, .search_btn i{
font-size: 15px;
}
.left_strip{
left: 110px;
}
.right_strip{
right: 100px;
}
.product_img{
width: 300px;
height: 300px;
}
.product_title{
font-size: 45px;
}
.product_title > sup{
font-size: 25px;
}
.product_type{
font-size: 18px;
}
.slide_nav_wrapper{
flex-direction: row;
left: 10px;
}
.dots_wrapper{
z-index: -1;
right: 10px;
}
.show{
right: 0;
}
}
/*===== MEDIA QUERIES (FOR MIN-WIDTH:768px) =====*/
@media screen and (min-width:768px) {
.nav__list{
display: flex;
}
.nav__item{
margin-bottom: 0;
margin-left: 2rem;
}
.menu_toggle_btn{
display: none;
}
.nav__item.search_btn, .nav__item.cart_btn{
display: none;
}
}
/*===== MEDIA QUERIES (FOR MIN-WIDTH:1200px) =====*/
@media screen and (min-width:1200px) {
.body_layout{
padding-left: 1.5rem;
padding-right: 2.2rem;
}
}
现在,看看最终效果,它在小尺寸设备上也能流畅运行。 *
现在让我们进入逻辑部分📖,即实现我们的脚本,使其能够在小型设备上切换。
菜单切换的JS语法:
// Toggle NAV-MENU
const toggleMenu = (toggleId, navId) => {
const toggle_btn = document.getElementById(toggleId),
nav = document.getElementById(navId)
if(toggle_btn && nav) {
toggle_btn.addEventListener('click', () => {
nav.classList.toggle('show')
})
}
}
toggleMenu('menu_toggle_btn', 'nav__menu');
输出 :
现在我们已经完成了90%的工作。接下来让我们开始剩下的10%的工作,也就是我们翘首以盼的JS动画😂
JS 动画会根据HTML 元素的类名进行抓取,以便使用 GSAP 为它们添加动画效果。
// CONTAINER's
gsap.from('.left_container', {
delay:2,
duration:1.5,
top:"100%",
ease:"expo.inOut"
});
gsap.from('.right_container', {
delay:2,
duration:1.5,
bottom:"100%",
ease:"expo.inOut"
});
// LOGO
gsap.from('.logo', {
opacity:0,
delay:3.3,
duration:2.5,
y:-20,
ease:"expo.inOut"
});
// NAV-ITEM
gsap.from('.nav__item', {
opacity:0,
delay:3.8,
duration:3,
y:25,
ease:"expo.Out",
stagger:.2
});
// SEARCH-BTN
gsap.from('.search_btn', {
opacity:0,
delay:4,
duration:3,
x:20,
ease:"expo.Out"
});
// CART-BTN
gsap.from('.cart_btn', {
opacity:0,
delay:4,
duration:3,
x:20,
ease:"expo.Out"
});
// SOCIAL-ITEM
gsap.from('.social_item', {
opacity:0,
delay:4.5,
duration:3,
x:-25,
ease:"expo.Out",
stagger:.2
});
// DIRECTION-BTN
gsap.from('.direction_btn', {
opacity:0,
delay:4.4,
x:-20,
ease:"power3.Out",
stagger:.2
});
// SLIDE
gsap.from('.dot', {
opacity:0,
delay:4.4,
x:-20,
ease:"power3.Out",
stagger:.2
});
// PRODUCT-IMG
gsap.from('.product_img', {
opacity:0,
delay:5,
duration:1.5,
ease:"expo.inOut",
});
// PRODUCT-TTTLE
gsap.from('.product_title', {
opacity:0,
delay:5.4,
duration:1.8,
y:100,
ease:"expo.inOut",
});
// PRODUCT-TYPE
gsap.from('.product_type', {
opacity:0,
delay:5.8,
duration:1.8,
y:100,
ease:"expo.inOut",
});
现在取消注释覆盖层 HTML 元素,然后在你的JS 文件中添加这些覆盖层脚本,见证奇迹吧!🙌
// OVERLAY
gsap.to('.first', {
delay:.5,
duration:1,
top:"-100%",
ease:"expo.inOut"
});
gsap.to('.second', {
delay:.7,
duration:1,
top:"-100%",
ease:"expo.inOut"
});
gsap.to('.third', {
delay:.9,
duration:1,
top:"-100%",
ease:"expo.inOut"
});
现在请看我们的最终成果:
结语:
非常感谢观看我的帖子!请考虑订阅,这将激励我创作更多类似的内容……
祝你编程愉快 🔥 !!!!!!
文章来源:https://dev.to/ananiket/create-a-responsive-landing-page-using-html-css-js-28ne












