Слайдер для сайта — html, css, javascript

В этой статье вы узнаете как создать слайдер. Он имеет красивую анимацию, которая позволит привлечь любого пользователя, за счет красивой визуализации. В слайдере используется особая навигационная система, которая делает его уникальным

Если у вас нет времени на изучение теоретической части.

Слайдер на Vue.js — отличное дополнение для любого сайта. В нем можно разместить любую необходимую информацию. Она будет легко восприниматься, пользователь сможет все изучить без каких-либо недоразумений. Такое преподнесение информации заинтересует пользователя так, что ему захочется изучить остальную. Благодаря этому потенциальный клиент сможет стать постоянным.

HTML-код

Для начала HTML — основа всех сайтов и каждой его части. С помощью него мы разместим весь контент слайдера и подключим необходимые скрипты и стили.

Сначала нужно создать блоки с частями внутреннего контента. Создаем основной контейнер с классом «wrapper», он будет содержать в себе все элементы слайдера.

После создания основы, мы разместим внутренние элементы. В них будет располагаться фоновое расположение, кнопки, а также основная информация.

При создании внутренних блоков мы обратимся к директивам vue.js:

V-for

Директива v-for отвечает за рендеринг элементов. Она задается внутри тегов, используя массив с их внутренними данными. Эту директиву можно применять к разным блокам, но в нашем случае используется тег div.

Для каждого v-for мы используем уникальные атрибуты index и slide. Таким образом мы получаем индексы элементов и данные для анимации слайда.

V-bind

Запись v-bind: class — позволяет управлять классами элемента. Она дает возможность добавлять новые классы и удалять их.

Запись v-bind: style — объект JavaScript. С виду строчка похожа на запись кода CSS, но это особый объект JS, который позволяет управлять стилями элемента.

В коде мы создаем основу для содержимого и навигационное поле, с помощью которого можно перемещаться между слайдами.

<div id="app" class="wrapper" v-cloak v-bind:class="{'is-previous':isPreviousSlide, 'first-load': isFirstLoad}">
   <div class="slide-wrapper" 
      v-for="(slide, index) in slides"
      v-bind:class="{ active: index === currentSlide }"
      v-bind:style="{ 'z-index': (slides.length - index), 'background-image': 'url(' + slide.bgImg + ')' }">
       <div class="slide-inner">
          <div class="slide-bg-text">
             <p>{{ slide.headlineFirstLine }}</p>
	 <p>{{ slide.headlineSecondLine }}</p>
         </div>
         <div class="slide-rect-filter">
         <div class="slide-rect" v-bind:style="{'border-image-source': 'url(' + slide.rectImg + ')'}">
         </div>
      </div>
      <div class="slide-content">
         <h1 class="slide-content-text">
            <p>{{ slide.headlineFirstLine }}</p>
	<p>{{ slide.headlineSecondLine }}</p>
        </h1><a class="slide-content-cta">Call To Action</a>
     </div>
    <h2 class="slide-side-text"><span>{{ slide.sublineFirstLine }} / </span><span>{{ slide.sublineSecondLine }}</span></h2>
   </div>
</div>
<div class="controls-container">
   <button class="controls-button"
      v-for="(slide, index) in slides"
      v-bind:class="{ active: index === currentSlide }"
      v-on:click="updateSlide(index)">{{ slide.headlineFirstLine }} {{ slide.headlineSecondLine }}</button>
</div>
<div class="pagination-container">
   <span class="pagination-item"
      v-for="(slide, index) in slides"
      v-bind:class="{ active: index === currentSlide }"
      v-on:click="updateSlide(index)"></span>
</div>
</div>

Вот что у нас получилось:

Красивый слайдер для сайта на Яваскрипт

CSS-стили

Для начала зададим стили для нашего слайда и его внутренних элементов.

Стили для внутренних элементов слайда

Задаем стили для общего контейнера с классом wrapper. В коде указана амперсанда &, не пугайтесь, это часть SCSS. Вместо неё можно использовать и обычное имя класса

Задаем позиционирование, ширину и фон для нашего слайда. Для этого используем параметры width, height, position и элементы background.

После оформления всего контейнера займемся стилизацией элементов. Задаем тени для текста и фон для его блоков, затем занимаемся оформлением фонового текста — шрифт, цвет и позиционирование. Чтобы разобраться в этом, внимательно изучите код css. Записи могут показаться вам сложными, но если изучить все элементы кода, он покажется вам простым.

.slide{
&-wrapper {
background-size: cover;
height: 100%;
background-position: center center;
position: absolute;
width: 100%;
background-blend-mode: darken;
&:nth-child(1) {
background-color: rgba(115, 129, 153, .4);
&:before {
background-color: rgba(115, 129, 153, .25);
}
.slide-content-text {
text-shadow: 2px 5px 45px rgba(85, 96, 113, 0.25);
}
}
&:nth-child(2) {
background-color: rgba(144, 171, 184, .7);
&:before {
background-color: rgba(144, 171, 184, .3);
}
.slide-content-text {
text-shadow: 2px 5px 45px rgba(121, 142, 152, 0.2);
}
}
&:nth-child(3) {
background-color: rgba(86, 125, 156, .5);
&:before {
background-color: rgba(86, 125, 156, 0.2);
}
.slide-content-text {
text-shadow: 2px 5px 55px rgba(57, 83, 103, 0.4);
}
}
&:before {
content: "";
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
}
}
&-inner {
position: relative;
z-index: 2;
height: 100%;
overflow: hidden;
}
&-bg-text {
font-family: 'Playfair Display';
color: #000;
font-size: 42vh;
line-height: .8;
opacity: .03;
font-weight: 900;
margin-top: -4rem;
position: absolute;
top: 50%;
left: 5vw;
transform: translateY(-50%);
> p:last-child {
padding-left: 4rem;
}
}
&-content {
color: #fff;
margin-top: 5rem;
position: absolute;
top: 50%;
left: calc(#{$left-offset} + (.7) * #{$rect-width});
transform: translateY(-50%);
display: flex;
flex-direction: column;
@include media(1000px) {
left: calc(#{$left-offset} + 1rem);
}
@include media-height(730px) {
top: 30%;
transform: translateY(-30%);
left: calc(#{$left-offset-small} + (.7) * #{$rect-width-small});
}
&-text {
font-family: 'Playfair Display';
font-size: 9rem;
letter-spacing: .2rem;
line-height: .87;
font-weight: 700;
will-change: auto;
@include media-height(790px) {
font-size: 7rem;
}
@include media(1150px) {
font-size: 7rem;
}
@include media(840px) {
font-size: 5.5rem;
}
@include media(630px) {
margin-bottom: 5.5rem;
}
@include media(500px) {
font-size: 3.5rem;
}
> p:last-child {
padding-left: 3rem;
}
}
&-cta {
@extend %callout;
cursor: pointer;
align-self: flex-start;
margin-top: 4.5rem;
margin-left: calc((.3) * 48vh + 4.5rem);
padding: .9rem 2.2rem;
border-left: 1px solid #fff;
border-right: 1px solid #fff;
transition: .18s ease-in-out;
font-weight: 700;
@include media(1000px) {
background-color: rgba(255, 255, 255, .3);
padding-top: 1.2rem;
padding-bottom: 1.2rem;
}
@include media(630px) {
display: none;
}
&:hover {
color: #000;
background-color: #fff;
}
}
}
&-rect {
height: $rect-height;
width: $rect-width;
border-image-slice: 10%;
position: absolute;
top: 50%;
transform: translateY(-50%);
left: $left-offset;
border-width: $rect-border-width;
border-style: solid;
box-shadow: 2px 2px 90px 30px rgba(41, 50, 61, 0.22);
will-change: auto;
@include media-height(790px) {
left: $left-offset-small;
height: $rect-height-small;
width: $rect-width-small;
border-width: $rect-border-width-small;
}
@include media-height(730px) {
top: 30%;
transform: translateY(-30%);
}
&-filter {
filter: brightness(110%) contrast(110%) saturate(110%);
}
}
&-side-text {
@extend %callout;
position: absolute;
left: calc(#{$left-offset} - 3rem);
writing-mode: vertical-rl;
top: calc((50% - (#{$rect-height} / 2)) + (#{$rect-border-width} / 2));
@include media-height(790px) {
left: calc(#{$left-offset-small} - 3rem);
top: calc((50% - (#{$rect-height-small} / 2)) + (#{$rect-border-width-small} / 2));
}
@include media-height(730px) {
top: calc((40% - (#{$rect-height-small} / 2)) + (#{$rect-border-width-small} / 2));
}
> span:first-child {
font-weight: 700;
}
&:after {
content: "";
width: 1px;
background-color: #fff;
height: 40px;
display: block;
position: absolute;
top: calc(100% + 25px);
left: 50%;
transform: translateX(-50%);
}
}
}

Навигация слайдера

После общей стилизации слайдера займемся навигационной панелью. Нам нужно сделать дизайн кнопок в панели навигации, которые будет использовать посетитель сайта.

В CSS коде мы изменим кнопки, зададим стили для их состояния. Таким образом, кнопки будут выглядеть по-разному в разных состояниях. Изменим цвет для активного состояния кнопки.

.controls{
&-container {
position: absolute;
z-index: 200;
display: flex;
bottom: 0;
right: 0;
align-items: flex-end;
@include media(630px) {
display: none;
}
}
&-button {
@extend %callout;
cursor: pointer;
background-color: rgba(208, 206, 204, .32);
border: 0;
padding: $control-btn-padding 2.2rem;
flex-basis: 0;
flex-grow: 1;
min-width: 15rem;
transition: .25s ease-in-out;
outline: 0;
@include media(730px) {
padding: 1.2rem 1.4rem;
min-width: 13rem;
}
&:not(.active) {
&:hover {
color: #000;
background-color: #fff;
}
}
&.active {
cursor: default;
font-weight: 700;
background-color: #3b3e45;
padding-top: $control-btn-padding + $control-active-btn-offset;
padding-bottom: $control-btn-padding + $control-active-btn-offset;
margin-bottom: -$control-active-btn-offset;
position: relative;
@include media(730px) {
padding-top: 1.4rem;
padding-bottom: 1.4rem;
margin-bottom: -0.15rem;
}
&:after {
content: "";
background-color: #e3e3e3;
height: 5px;
width: calc(100% - 8px);
position: absolute;
top: 100%;
left: 4px;
}
}
&:not(.active) + & {
border-left: 1px solid rgba(255, 255, 255, .2);
}
}
}

Анимация слайдера

Теперь самый интересный и сложный этап стилизации. Наша задача состоит в том, чтобы создать красивую анимацию, а также сделать слайдер адаптивным.

$slide-swipe: .9s;
$text-cut-up: .5s;
@keyframes slideLeft {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}

@keyframes slideRight {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}

@keyframes cutTextUp {
from {
clip-path: inset(0 0 -10% 0);
}
to {
clip-path: inset(0 0 100% 0);
}
}

@keyframes cutTextDown {
from {
clip-path: inset(100% 0 0 0);
}
to {
clip-path: inset(-10% 0 -20% 0);
opacity: 1;
}
}

@keyframes cutTextDownFromTop {
from {
clip-path: inset(0 0 100% 0);
}
to {
clip-path: inset(0 0 -30% 0);
opacity: 1;
}
}

@keyframes rectMovement {
0% {
transform: translateX(0) rotate(0) translateY(-50%);
}
60% {
opacity: 1;
}
100% {
transform: translateX(calc(-#{$rect-width} + -#{$left-offset})) rotate(12deg) translateY(-50%);
opacity: 0;
}
}

@include media-height(730px) {
@keyframes rectMovement {
0% {
transform: translateX(0) rotate(0) translateY(-30%);
}
60% {
opacity: 1;
}
100% {
transform: translateX(calc(-#{$rect-width} + -#{$left-offset})) rotate(12deg) translateY(-30%);
opacity: 0;
}
}
}

@keyframes rectMovementFromRight {
0% {
transform: translateX(calc(#{$rect-width})) rotate(12deg) translateY(-50%);
opacity: 0;
}
60% {
opacity: 1;
}
100% {
transform: translateX(0) rotate(0) translateY(-50%);
opacity: 1;
@include media-height(730px) {
transform: translateX(0) rotate(0) translateY(-30%);
}
}
}

@include media-height(730px) {
@keyframes rectMovementFromRight {
0% {
transform: translateX(calc(#{$rect-width})) rotate(12deg) translateY(-30%);
opacity: 0;
}
60% {
opacity: 1;
}
100% {
transform: translateX(0) rotate(0) translateY(-30%);
opacity: 1;
}
}
}

@keyframes rectMovementRight {
0% {
transform: translateX(calc(-#{$rect-width} + -#{$left-offset})) rotate(12deg) translateY(-50%);
}
40% {
opacity: 1;
}
100% {
transform: translateX(0) rotate(0) translateY(-50%);
opacity: 1;
@include media-height(730px) {
transform: translateX(0) rotate(0) translateY(-30%);
}
}
}

@include media-height(730px) {
@keyframes rectMovementRight {
0% {
transform: translateX(calc(-#{$rect-width} + -#{$left-offset})) rotate(12deg) translateY(-30%);
}
40% {
opacity: 1;
}
100% {
transform: translateX(0) rotate(0) translateY(-30%);
opacity: 1;
}
}
}

@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

.slide-wrapper {
opacity: 0;
transition-delay: $slide-swipe + $text-cut-up;
transition-duration: 0s;
transition-property: opacity;
will-change: opacity, transform;
&:not(.active) {
animation-delay: $text-cut-up;
animation-name: slideLeft;
animation-duration: $slide-swipe;
animation-timing-function: cubic-bezier(0.18, 0.54, 0.52, 0.93);
pointer-events: none;
.slide-content-text > p,
.slide-side-text {
animation-name: cutTextUp;
animation-duration: $text-cut-up;
animation-timing-function: ease-out;
}
.slide-rect {
animation-name: rectMovement;
animation-duration: $text-cut-up;
animation-timing-function: ease;
animation-fill-mode: forwards;
}
}
&.active {
transition-delay: 0s;
opacity: 1;
.slide-content-text > p {
opacity: 0;
animation-delay: $text-cut-up + .3s;
animation-name: cutTextDown;
animation-duration: $text-cut-up;
animation-timing-function: ease;
animation-fill-mode: forwards;
}
.slide-rect {
opacity: 0;
animation-name: rectMovementFromRight;
animation-duration: $text-cut-up - .05s;
animation-timing-function: ease;
animation-fill-mode: forwards;
animation-delay: $slide-swipe;
}
}
.is-previous & {
&:not(.active) {
animation: none;
.slide-rect {
animation: none;
}
}
&.active {
transform: translateX(-100%);
animation-fill-mode: forwards;
animation-delay: $text-cut-up;
animation-name: slideRight;
animation-duration: $slide-swipe - .1s;
animation-timing-function: cubic-bezier(0.18, 0.54, 0.52, 0.93);
.slide-rect {
opacity: 0;
animation-name: rectMovementRight;
animation-duration: $text-cut-up;
animation-timing-function: ease-out;
animation-fill-mode: forwards;
animation-delay: $slide-swipe;
}
}
}
}

.first-load {
.slide-wrapper.active .slide-side-text,
.slide-wrapper.active .slide-content-cta,
.slide-wrapper.active .slide-rect,
.controls-container {
opacity: 0;
animation-name: fadeIn;
animation-delay: .3s;
animation-duration: .3s;
animation-fill-mode: forwards;
animation-timing-function: ease-in;
}
.slide-wrapper.active .slide-content-text > p {
animation-name: fadeIn;
animation-delay: $text-cut-up;
animation-duration: $text-cut-up + .2s;
}
}

JS скрипты

var app = new Vue({
el: '#app',
data: {
currentSlide: 0,
isPreviousSlide: false,
isFirstLoad: true,
slides: [
{
headlineFirstLine: "Lorem",
headlineSecondLine: "Vitaer",
sublineFirstLine: "Nihil sub sole",
sublineSecondLine: "novum",
bgImg: "/codepens/slide0.jpg",
rectImg: "/codepens/slide-rect0.jpg"
},
{
headlineFirstLine: "Nulla",
headlineSecondLine: "Auctor",
sublineFirstLine: "Il n'y a rien de neuf sous",
sublineSecondLine: "le soleil",
bgImg: "/codepens/slide1.jpg",
rectImg: "/codepens/slide-rect1.jpg"
},
{
headlineFirstLine: "Nullam",
headlineSecondLine: "Ultricies",
sublineFirstLine: "Τίποτα καινούργιο κάτω από",
sublineSecondLine: "τον ήλιο",
bgImg: "/codepens/slide2.jpg",
rectImg: "/codepens/slide-rect2.jpg"
}
]
},
mounted: function () {
var productRotatorSlide = document.getElementById("app");
var startX = 0;
var endX = 0;

productRotatorSlide.addEventListener("touchstart", (event) => startX = event.touches[0].pageX);

productRotatorSlide.addEventListener("touchmove", (event) => endX = event.touches[0].pageX);

productRotatorSlide.addEventListener("touchend", function(event) {
var threshold = startX - endX;

if (threshold < 150 && 0 < this.currentSlide) {
this.currentSlide--;
}
if (threshold > -150 && this.currentSlide < this.slides.length - 1) {
this.currentSlide++;
}
}.bind(this));
},
methods: {
updateSlide(index) {
index < this.currentSlide ? this.isPreviousSlide = true : this.isPreviousSlide = false;
this.currentSlide = index;
this.isFirstLoad = false;
}
}
})

Внимательно просмотрите код

Для тех, кто только начал изучать JavaScript, эти записи могут показаться очень сложными, но в них также нужно разобраться.

Общая цель этой записи состоит в том, чтобы разместить описание и картинки на слайдере.

Итак, вот финальная версия нашего слайдера

Заключение

Vue.js — отличный фреймворк, который позволяет создавать отличные элементы веб-дизайна. Теперь вы убедились в этом лично. Слайдер получился красивым и функциональным.

Чтобы закрепить эти знания, просто найдите и изучите информацию об отдельных частях кода. Это может занять немало времени, но вы получите отличный результат. Удачи!

Теги:
0

Оставить своё мнение

Ваш e-mail не будет опубликован. Обязательные поля помечены *