Como Criar uma Barra de Progresso Responsiva e Dinâmica com HTML, CSS e JavaScript
Texto traduzido por Daniel Rosa
Um tutorial completo para você criar uma barra de progresso responsiva e dinâmica com HTML, CSS e JavaScript.
O objetivo é criar uma barra de progresso responsiva, simples e eficaz, que faça o seguinte:
- Tenha quatro etapas até a conclusão.
- Cada etapa tenha um estado
default
,active
ecomplete
. - Seja possível avançar de uma etapa para a próxima até a conclusão.
HTML
Para reduzir a redundância e aumentar a possibilidade de reutilização, rastreamos todo o state em um componente do Vue. No DOM, isso gera dinamicamente um número qualquer de etapas exigidas.
Observação: É possível fazer isso em JavaScript (ECMAScript) puro ou com qualquer outro framework de front-end. O uso do Vue é para fins de demonstração.
A barra de progresso usa uma marcação em HTML básica. Nela, temos:
- um contêiner com as classes computadas na etapa atual:
progressClasses
- uma faixa estática em segundo plano:
progress__bg
- um laço que percorre cada etapa e aplica
stepClasses
com base na etapa atual.
Cada etapa tem:
- um
progress__indicator
, que contém um ícone de verificação o qual fica visível quando a etapa foi concluída. - um
progress__label
, que contém o texto de rótulo daquela etapa.
<div
id="app"
:class="progressClasses"
>
<div class="progress__bg"></div>
<template v-for="(step, index) in steps">
<div :class="stepClasses(index)">
<div class="progress__indicator">
<i class="fa fa-check"></i>
</div>
<div class="progress__label">
{{step.label}}
</div>
</div>
</template>
<div class="progress__actions">
<div
class="btn"
v-on:click="nextStep(false)"
>
Back
</div>
<div
class="btn"
v-on:click="nextStep"
>
Next
</div>
<div>
Step:
{{currentStep ? currentStep.label : "Start"}}
</div>
</div>
</div>
Para simplificar, progress__actions
, que controla a direção na qual a barra progride, é aninhada dentro da própria barra de progresso.
CSS (SCSS)
É aqui que fazemos todo o trabalho pesado. As classes definidas aqui serão aplicadas dinamicamente pelo JS com base na etapa atual.
Primeiro, vamos selecionar algumas cores com as quais trabalharemos (dois tons de cinza, azul, verde e branco, nessa ordem):
$gray: #E5E5E5;
$gray2: #808080;
$blue: #2183DD;
$green: #009900;
$white: #FFFFFF;
Em seguida, definimos a classe .progress
: o contêiner que une todo o conteúdo da barra de progresso.
.progress {
position: absolute;
top: 15vh;
width: 0%;
height: 10px;
background-color: $blue;
transition: width .2s;
}
Nossa barra de progresso precisa de um .progress__bg
, que nossas etapas de progresso percorrerão como se fosse uma trilha. A trilha será cinza, mudando de cor (sendo coberta por essa outra cor) à medida que avançamos para uma próxima etapa.
.progress__bg {
position: absolute;
width: 100vw;
height: 10px;
background-color: $gray;
z-index: -1;
}
Cada .progress__step
contém o espaço circular da etapa que ficará em destaque e que se preencherá quando a barra de progresso for avançando.
.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);
}
}
}
Elas também contém o .progress__indicator
circular e o texto do rótulo, .progress__label
. O estilo padrão é definido fora de .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;
}
Vamos continuar o aninhamento dentro de .progress__step
e definir a etapa em seu estado active (ativo).
&.progress__step--active {
color: $blue;
font-weight: 600;
}
A seguir, definimos a etapa em seu estado complete (concluído). Observação: os estilos padrão para .progress__indicator
e para .progress__label
são sobrescritos no estado concluído.
&.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
Como mencionamos antes, esta parte será diferente com base no modo como você implementará a lógica das etapas – dependendo do tamanho do contexto em que ela for implementada, dos frameworks e dos padrões que serão utilizados e assim por diante.
Este exemplo usa um componente do Vue para demonstrar:
- o cálculo de classes para a barra de progresso com base no estado atual.
- o cálculo de classes para cada etapa com base no estado atual.
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)
// lidando com o retorno
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" }
}
// lidando com o avanço
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}`
}
}
})
Resultado final
Confira aqui o CodePen para ver um exemplo funcional.
Agora, seu tutorial está completo e pronto para ser compartilhado com outras pessoas que desejam aprender a criar uma barra de progresso responsiva e dinâmica.
Confira também:
Sobre o Autor
0 Comentários