先上效果图:
备注:这个效果图太大了,压缩了一下效果有点不咋好看。感兴趣同学们可以自己运行代码看一下,保证不会失望~
再上代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
:root {
--height: calc( 80vh - 50px );
--width: 450px;
}
.carousel {
display: grid;
transform: translate3d(0,0,0.1px);
}
.carousel__list {
display: flex;
overflow: hidden;
list-style: none;
padding: 2em 0 3em;
margin: 0;
contain: layout;
isolation: isolate;
}
.carousel__item {
display: grid;
position: relative;
align-content: start;
margin: 0 10px;
padding: 0;
flex: 1 1 10%;
height: var(--height);
overflow: hidden;
background: rgba(255,255,255,0.2);
border-radius: 16px;
transform: translate3d(0,0,0.1px);
box-shadow: rgba(0, 0, 0, 0.4) 0px 3px 15px 2px, rgba(0, 0, 0, 0.2) 0px 12px 28px 0px, rgba(0, 0, 0, 0.1) 0px 2px 4px 0px, rgba(255, 255, 255, 0.05) 0px 0px 0px 1px inset;
contain: layout;
isolation: isolate;
}
.carousel__item,
.carousel__item * {
transition: all .6s cubic-bezier(.55,.24,.18,1);
user-select: none;
}
.carousel__image,
.carousel__contents {
width: var(--width);
height: auto;
}
.carousel__item:hover {
flex-basis: calc( var(--width) / 2 );
transition: all 0.3s ease;
}
.carousel__item[data-active] {
flex-basis: var(--width);
flex-grow: 0;
}
@media screen and (max-width: 800px) {
.carousel__item {
flex-basis: 15%;
}
}
@media screen and (max-width: 600px) {
.carousel__item {
flex-basis: 10%;
margin: 0 5px;
border-radius: 8px;
font-size: 3vw;
}
.carousel__item[data-active] {
flex-basis: 45%;
flex-grow: 0;
}
.carousel__item:nth-child(3),
.carousel__item:nth-child(7) {
flex: 0 0 10px;
}
.carousel__item:nth-child(2),
.carousel__item:nth-child(8) {
flex: 0 0 5px;
transform: translateX(-50px);
}
.carousel__item:nth-child(8) {
transform: translateX(50px);
}
.carousel__item:nth-child( 1 ),
.carousel__item:nth-child( n + 9 ) {
flex: 0 0 0px;
margin: 0;
box-shadow: none;
opacity: 0!important;
}
.carousel__item:not(:nth-child( n + 5 )) img,
.carousel__item:nth-child( n + 7 ) img {
opacity: 0.8;
}
.carousel__item:not(:nth-child( n + 4 )) *,
.carousel__item:nth-child( n + 7 ) * {
opacity: 0!important;
}
}
@media screen and (min-width: 600px) {
.carousel__item:nth-child(3),
.carousel__item:nth-child(10) {
flex: 0 0 10px;
}
.carousel__item:nth-child(2),
.carousel__item:nth-child(11) {
flex: 0 0 5px;
transform: translateX(-50px);
}
.carousel__item:nth-child(11) {
transform: translateX(50px);
}
.carousel__item:nth-child( 1 ),
.carousel__item:nth-child( n + 12 ) {
flex: 0 0 0px;
margin: 0;
box-shadow: none;
opacity: 0!important;
}
.carousel__item:not(:nth-child( n + 5 )) img,
.carousel__item:nth-child( n + 9 ) img {
opacity: 0.8;
}
.carousel__item:not(:nth-child( n + 4 )) *,
.carousel__item:nth-child( n + 10 ) * {
opacity: 0!important;
}
}
.carousel__item img {
display: block;
position: absolute;
width: var(--width);
height: 100%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
z-index: -1;
aspect-ratio: 2/3;
object-fit: cover;
filter: saturate(0.2) contrast(0.75) brightness(1.1);
}
.carousel__item::after {
content: "";
position: absolute;
inset: 0;
width: 100%;
height: 100%;
z-index: 1;
opacity: 1;
background: linear-gradient(160deg, rgba(2,0,36,0) 40%, rgba(118,221,136,.5) 70%, rgba(0,255,246,.6) 100%);
transition: all .66s cubic-bezier(.55,.24,.18,1);
}
.carousel__item[data-active]::after {
transform: translateY(100%);
}
.carousel__item[data-active],
.carousel__item[data-active] * {
opacity: 1;
filter: none;
}
.carousel__contents {
display: flex;
flex-direction: column-reverse;
justify-content: start;
min-height: 200px;
padding: 1em;
z-index: 2;
background-image: radial-gradient( ellipse at 0px 0px, rgba(0,0,0,0.4) 20%, transparent 50% );
background-size: 170% 200px;
background-repeat: no-repeat;
position: absolute;
top: 0;
left: 0;
}
.carousel__contents .user__name {
color: #e8eff4;
font-size: 1.75em;
font-weight: 600;
letter-spacing: .8px;
text-shadow: 0 1px 0 rgba(0,0,0,0.3);
}
.carousel__contents .user__title {
font-family: lexend;
font-size: .875em;
letter-spacing: 1.25px;
font-weight: 500;
text-transform: uppercase;
color: transparent;
background: linear-gradient( 270deg, rgb(67, 255, 0), rgb(0, 255, 247) );
background-clip: text;
-webkit-background-clip: text;
opacity: 0.85;
text-wrap: balance;
margin-bottom: 0.5em;
}
.carousel__contents .user__title,
.carousel__contents .user__name {
margin: 0;
line-height: 1.1;
opacity: 0;
transform: translateX(-200px);
transition-duration: 1s;
max-width: 18em;
}
@media screen and (max-width: 800px) {
.carousel__item img {
width: calc(var(--width) * .5);
}
.carousel__contents {
transform: translateX(-100%) rotate(90deg);
transform-origin: bottom right;
align-items: end;
justify-content: end;
background-image: radial-gradient( ellipse at 100% 100%, rgba(0, 0, 0,.4) 0%, transparent 50% );
background-position: -100% 100%;
flex-direction: column;
position: absolute;
bottom: 0;
left: 0;
text-align: right;
}
[data-active] .carousel__contents {
background-position: 100% 100%;
}
.carousel__contents .user__title,
.carousel__contents .user__name {
max-width: 70vh;
transform: translateX(200px);
}
}
[data-active] .carousel__contents * {
transform: translateX(0px);
transition-duration: 0.66s;
opacity: 1;
}
[data-active] .carousel__contents .user__name {
transition-delay: 0.1s;
}
[data-active] .carousel__contents .user__title {
opacity: 0.85;
transition-delay: 0.05s;
}
/*
non-demo css
*/
.carousel__nav {
padding: 1em;
justify-self: end;
grid-row: 1;
display: flex;
justify-content: space-between;
gap: 1em;
}
button {
display: flex;
gap: .5em;
padding: 0.5em 1.5em;
}
button span,
button svg {
margin: 0;
padding: 0;
fill: none;
}
button path {
fill: currentColor;
}
body, html {
padding: 0;
align-items: start;
}
</style>
</head>
<body>
<main id="app">
<section class="carousel">
<ul class="carousel__list">
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Anthony Lee</h2>
<h3 class="user__title">Archetypal Professor of Recognition</h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1544005313-94ddf0286df2?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Alicia Chevalier</h2>
<h3 class="user__title">Corporate Usability Analyst</h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Nate Boucher</h2>
<h3 class="user__title">Customer Impact Officer</h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1614204424926-196a80bf0be8?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Leah Harris</h2>
<h3 class="user__title">Designer and Bandit</h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0" data-active="data-active">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1536766768598-e09213fdcf22?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Angelina Laurent</h2>
<h3 class="user__title">Oracle for Inspiration</h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Gal Gadot</h2>
<h3 class="user__title">Acting Designer and Consultant</h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1590086782792-42dd2350140d?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Albert Sørensen</h2>
<h3 class="user__title">Neural Big Shot of Anticipation</h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1553514029-1318c9127859?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Candice Marchand</h2>
<h3 class="user__title">Mindful Realist of Motion Laws </h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1596813362035-3edcff0c2487?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Jennifer Salazar</h2>
<h3 class="user__title">Design Habitué</h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1552374196-c4e7ffc6e126?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Antonin Dufour</h2>
<h3 class="user__title">Human-Centered Designer</h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1530785602389-07594beb8b73?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Melissa Simon</h2>
<h3 class="user__title">International Infrastructure Analyst</h3>
</div>
</div>
</li>
<li class="carousel__item" tabindex="0">
<div class="carousel__box">
<div class="carousel__image"><img src="https://images.unsplash.com/photo-1560250097-0b93528c311a?fit=crop&h=720&q=80" width="480" height="720"/></div>
<div class="carousel__contents">
<h2 class="user__name">Brandon Murray</h2>
<h3 class="user__title">Central Functionality VP</h3>
</div>
</div>
</li>
</ul>
<div class="carousel__nav">
<button class="prev">
<svg width="24" height="24" viewBox="0 0 24 24">
<path d="M9.586 4l-6.586 6.586a2 2 0 0 0 0 2.828l6.586 6.586a2 2 0 0 0 2.18 .434l.145 -.068a2 2 0 0 0 1.089 -1.78v-2.586h7a2 2 0 0 0 2 -2v-4l-.005 -.15a2 2 0 0 0 -1.995 -1.85l-7 -.001v-2.585a2 2 0 0 0 -3.414 -1.414z"></path>
</svg><span>prev</span>
</button>
<button class="next"><span>next</span>
<svg width="24" height="24" viewBox="0 0 24 24">
<path d="M12.089 3.634a2 2 0 0 0 -1.089 1.78l-.001 2.586h-6.999a2 2 0 0 0 -2 2v4l.005 .15a2 2 0 0 0 1.995 1.85l6.999 -.001l.001 2.587a2 2 0 0 0 3.414 1.414l6.586 -6.586a2 2 0 0 0 0 -2.828l-6.586 -6.586a2 2 0 0 0 -2.18 -.434l-.145 .068z"></path>
</svg>
</button>
</div>
</section>
</main>
<a class="social-icon codepen" href="https://blog.csdn.net/qq_35241329?type=blog" title="view my codepens">
<span>仅用于学习交流</span>
</a>
</body>
<script>
const d = document;
const $q = d.querySelectorAll.bind(d);
const $g = d.querySelector.bind(d);
const $prev = $g(".prev");
const $next = $g(".next");
const $list = $g(".carousel__list");
let auto;
let pauser;
const getActiveIndex = () => {
const $active = $g("[data-active]");
return getSlideIndex($active);
}
const getSlideIndex = ($slide) => {
return [...$q(".carousel__item")].indexOf( $slide );
}
const prevSlide = () => {
const index = getActiveIndex();
const $slides = $q(".carousel__item");
const $last = $slides[$slides.length-1];
$last.remove();
$list.prepend($last);
activateSlide( $q(".carousel__item")[index] );
}
const nextSlide = () => {
const index = getActiveIndex();
const $slides = $q(".carousel__item");
const $first = $slides[0];
$first.remove();
$list.append($first);
activateSlide( $q(".carousel__item")[index] );
}
const chooseSlide = (e) => {
const max = (window.matchMedia("screen and ( max-width: 600px)").matches) ? 5 : 8;
const $slide = e.target.closest( ".carousel__item" );
const index = getSlideIndex( $slide );
if ( index < 3 || index > max ) return;
if ( index === max ) nextSlide();
if ( index === 3 ) prevSlide();
activateSlide($slide);
}
const activateSlide = ($slide) => {
if (!$slide) return;
const $slides = $q(".carousel__item");
$slides.forEach(el => el.removeAttribute('data-active'));
$slide.setAttribute( 'data-active', true );
$slide.focus();
}
const autoSlide = () => {
nextSlide();
}
const pauseAuto = () => {
clearInterval( auto );
clearTimeout( pauser );
}
const handleNextClick = (e) => {
pauseAuto();
nextSlide(e);
}
const handlePrevClick = (e) => {
pauseAuto();
prevSlide(e);
}
const handleSlideClick = (e) => {
pauseAuto();
chooseSlide(e);
}
const handleSlideKey = (e) => {
switch(e.keyCode) {
case 37:
case 65:
handlePrevClick();
break;
case 39:
case 68:
handleNextClick();
break;
}
}
const startAuto = () => {
auto = setInterval( autoSlide, 3000 );
}
startAuto();
$next.addEventListener( "click", handleNextClick );
$prev.addEventListener( "click", handlePrevClick );
// $list.addEventListener( "click", handleSlideClick );
$list.addEventListener( "focusin", handleSlideClick );
$list.addEventListener( "keyup", handleSlideKey );
</script>
</html>