Як створити чуйну та динамічну панель прогресу за допомогою HTML, CSS та JavaScript

Кілька років тому я написав коротку статтю про створення адаптивного бару прогресу. З тих пір мої методики розвивались, і тому оновлення в порядку.

Найбільша зміна полягає в тому, що псевдоелементи (до, після) більше не потрібні. Тепер CSS стало простішим, DOM легше читати і він набагато динамічніший.

Тож спробуємо ще раз.

Наша мета - створити простий та ефективний адаптивний індикатор прогресу, який робить наступне:

  • Має чотири кроки до завершення.
  • Кожен крок має default, activeі completeстан.
  • Може прогресувати від кроку до кроку до завершення.

Перегляньте CodePen тут, щоб переглянути приклад.

HTML

Щоб зменшити надмірність і збільшити повторне використання, ми відстежуємо всі стани в компоненті Vue. У DOM це динамічно генерує будь-яку кількість необхідних кроків.

Примітка : Власний JavaScript (ECMAScript) або будь-який інший фреймворк може досягти цього. Використання Vue призначене для демонстрації.

На панелі виконання використовується основна розмітка. Є:

  • контейнер з обчислюваними класами на основі поточного кроку: progressClasses
  • статична фонова доріжка: progress__bg
  • цикл, який перебирає кожен крок і застосовується stepClassesна основі поточного кроку.

Кожен крок має:

  • a, progress__indicatorщо містить піктограму перевірки, яка видно, якщо крок завершено.
  • a, progress__labelщо містить текст мітки для цього кроку.
 {{step.label}} Back Next Step: {{currentStep ? currentStep.label : "Start"}} 

Для простоти, progress__actionsякі контролюють напрямок руху, вкладені в саму панель виконання.

CSS (SCSS)

Тут ми робимо важку атлетику. Визначені тут класи застосовуватимуться JS динамічно на основі поточного кроку.

Спочатку давайте виділимо кілька кольорів для роботи:

$gray: #E5E5E5; $gray2: #808080; $blue: #2183DD; $green: #009900; $white: #FFFFFF;

Тепер визначте .progressклас: контейнер, який вміщує вміст індикатора виконання.

.progress { position: absolute; top: 15vh; width: 0%; height: 10px; background-color: $blue; transition: width .2s; }

Нашій панелі прогресу потрібно, .progress__bgщоб кроки прогресу перебігали як трек. Це буде сірим кольором, покритим кольоровою смужкою під час переходу до наступного кроку.

.progress__bg { position: absolute; width: 100vw; height: 10px; background-color: $gray; z-index: -1; }

Кожен .progress__stepмістить круглий крок, який буде виділятися та заповнюватися в міру просування індикатора прогресу.

.progress__step { position: absolute; top: -8px; left: 0; display: flex; flex-direction: column; align-items: center; text-align: center; @for $i from 1 through 5 { &.progress__step--#{$i} { left: calc(#{$i * 20}vw - 9px); } } }

Він також містить круглий .progress__indicatorтекст та текст етикетки .progress__label. Їх стилі за замовчуванням визначені за межами .progress__step.

.progress__indicator { width: 25px; height: 25px; border: 2px solid $gray2; border-radius: 50%; background-color: $white; margin-bottom: 10px; .fa { display: none; font-size: 16px; color: $white; } } .progress__label { position: absolute; top: 40px; }

Давайте продовжимо знову гніздитися всередині .progress__stepта визначимо крок у його активному стані.

&.progress__step--active { color: $blue; font-weight: 600; }

Далі визначте крок у його повному стані. Примітка : стилі за замовчуванням для .progress__indicatorі .progress__labelзамінюються, коли вони у повному стані.

&.progress__step--complete { .progress__indicator { background-color: $green; border-color: $blue; color: $white; display: flex; align-items: center; justify-content: center; } .progress__indicator .fa { display: block; } .progress__label { font-weight: 600; color: $green; } }

JavaScript

Як уже згадувалося раніше, це буде відрізнятися залежно від того, як ви реалізуєте логіку кроків, більший контекст, в якому він реалізований, які фреймворки та шаблони ви використовуєте тощо.

Цей приклад використовує компонент Vue для демонстрації:

  • розрахунок класів для індикатора прогресу на основі поточного стану.
  • розрахунок класів для кожного кроку на основі поточного стану.
var app = new Vue({ el: '#app', data: { currentStep: null, steps: [ {"label": "one"}, {"label": "two"}, {"label": "three"}, {"label": "complete"} ] }, methods: { nextStep(next=true) { const steps = this.steps const currentStep = this.currentStep const currentIndex = steps.indexOf(currentStep) // handle back if (!next) { if (currentStep && currentStep.label === 'complete') { return this.currentStep = steps[steps.length - 1] } if (steps[currentIndex - 1]) { return this.currentStep = steps[currentIndex - 1] } return this.currentStep = { "label": "start" } } // handle next if (this.currentStep && this.currentStep.label === 'complete') { return this.currentStep = { "label": "start" } } if (steps[currentIndex + 1]) { return this.currentStep = steps[currentIndex + 1] } this.currentStep = { "label": "complete" } }, stepClasses(index) { let result = `progress__step progress__step--${index + 1} ` if (this.currentStep && this.currentStep.label === 'complete' || index < this.steps.indexOf(this.currentStep)) { return result += 'progress__step--complete' } if (index === this.steps.indexOf(this.currentStep)) { return result += 'progress__step--active' } return result } }, computed: { progressClasses() { let result = 'progress ' if (this.currentStep && this.currentStep.label === 'complete') { return result += 'progress--complete' } return result += `progress--${this.steps.indexOf(this.currentStep) + 1}` } } })

Висновок

В кінці всього у вас є таке:

Перегляньте CodePen на живому прикладі.

Якщо ви вважаєте мої статті корисними, будь ласка, подумайте про те, щоб стати членом мого Patreon :)

Або якщо ви просто хочете купити мені каву (я люблю каву):