Кілька років тому я написав коротку статтю про створення адаптивного бару прогресу. З тих пір мої методики розвивались, і тому оновлення в порядку.
Найбільша зміна полягає в тому, що псевдоелементи (до, після) більше не потрібні. Тепер 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 :)
Або якщо ви просто хочете купити мені каву (я люблю каву):