05 de agosto de 2017 • 5 min de leitura
Criando Reading Progress com CSS Variables
Uma forma fácil de implementar uma barra de reading progress em poucas linhas.
Introdução
Faaala pessoal, nem era a ideia escrever um post hoje não, mas o tempinho aqui em Petrópolis está meio chuvoso e friozinho. Coloquei para tocar Donovan Woods que é um cantor canadense que toca um Folk bem calminho, e pensei, por que não escrever um post?
CSS Variables
O post de hoje eu vou utilizar uma feature bem maneira que é a CSS Variables, basicamente é a possibilidade de utilizar variáveis dentro do CSS de forma nativa! Isso não é demais? =D
E sempre quando se fala de algo novo, vem a primeira pergunta ahhh, mas isso não deve pegar em lugar nenhum!
. Só que é aí que você se engana. O suporte é até bem legal como você pode ver aqui no Can I use, basicamente Firefox, Chrome, Android Browser e até o Safari! Não funciona no IE, mas quem se importa? =p
A outra pergunta comum é: Mas por que usar isso? Já tenho no meu pre-processador.
, bom isso é uma verdade, o pre-processador ajuda pacas e possui várias coisas legais para brincar, inclusive variáveis. Mas essas variáveis ficam somente naquele momento, depois você gera o CSS final e essas variáveis somem. Aqui não é o caso, a variável está disponível no Browser para você poder criar várias brincadeiras, como a que vamos fazer, por exemplo.
Básico do CSS Variables
Bom, vamos logo para a parte prática que é mais interessante. Digamos que eu tenha um site e eu quero que o header tenha cores diferentes se estiver na home ou em páginas normais. Seguindo o seguinte html:
<!-- Página Home -->
<html>
<body class="home">
<header class="header"></header>
...
<body>
</html>
<!-- Página Contact -->
<html>
<body class="page page-contact">
<header class="header"></header>
...
<body>
</html>
Tendo em vista o seguinte markup, podemos criar um css assim:
:root {
--header-home-bg-color: blue;
--header-pages-bg-color: white;
}
.home .header {
background-color: var(--header-home-bg-color);
}
.page .header {
background-color: var(--header-pages-bg-color);
}
Bastante intuitivo né? Mas vamos as explicações de como funciona. Para você definir uma variável no CSS, basta utilizar esses dois traços no início da variável, --variavel-linda
e para utilizar o valor dela, é só chamar dentro do var(--variavel-linda)
. Sim gente, é só isso. Precisa de mais nada! E outra coisa bastante legal, o var
pode receber dois parâmetros, um que é sua variável e o outro que é um fallback caso o valor da sua variável seja inválido. Por exemplo:
:root {
--font-stack: 'Open Sans';
}
body {
font-family: var(--font-stack, 'Arial');
}
Caso o valor de --font-stack
não fosse achado ou válido, ele iria utilizar o valor Arial
.
Integrando com Javascript e criando nosso Reading
Claro que precisamos integrar isso com JS né? E é também simples demais. Basta utilizar o método setProperty
do style
no elemento que você desejar.
Primeiro vamos criar nosso html bem bobo, que vai ser um grande texto num container. E o item principal, nossa div progress
, que vai ser responsável por fazer a barrinha de progresso no topo.
<div class="progress"></div>
<div class="container">
<!-- texto -->
</div>
Depois vamos criar nosso CSS para o progress
.
.progress {
background: linear-gradient(to right, #3863a0 var(--scroll), transparent 0);
background-repeat: no-repeat;
position: fixed;
width: 100%;
height: 8px;
z-index: 2;
}
Reparem que eu estou utilizando uma variável ali que é var(--scroll)
e também reparem que eu não criei ela no CSS, pois eu vou criar no meu JS.
Para fazer o cálculo do scroll e identificar o progresso, vamos utilizar algums métodos do JS, que são:
- clientHeight - permite verificar a altura da janela do browser, ou seja, só a parte visível da sua tela.
- scrollTop - verifica a distância do topo da página até o topo da primeira parte visível da tela. Dá uma olhada no link, lá tem uma imagem bem explicativa.
- scrollHeight - verifica a altura do elemento, considerando suas partes não visíveis.
Tendo esses métodos em mente, fica fácil criar a seguinte função:
const progress = document.querySelector('.progress')
const body = document.body
const page = document.documentElement
let scroll
document.addEventListener('scroll', function () {
scroll = (body.scrollTop / (body.scrollHeight - page.clientHeight)) * 100
progress.style.setProperty('--scroll', scroll + '%')
})
Primeiro eu verifico a altura do topo da página até o topo do meu elemento (body.scrollTop) e então divido pelo tamanho total do meu elemento menos a altura do browser, isso multiplicado por 100, para poder obter a porcentagem do quanto eu já desci na tela.
Tendo esse valor fica fácil, basta definir esse valor dentro de progress
, para isso eu uso o método setProperty
, que vai definir o valor da variável --scroll
e assim vai aumentar e diminuir o background do meu elemento, fazendo o efeito de progresso na leitura.
Abaixo você pode ver esse exemplo rodando:
Conclusão
Bom galera, espero que tenham gostado do post, é bem simplão, mas é bem maneiro. E mostra como as CSS Variables podem se tornar ótimas ferramentas no futuro. Eu aconselho a assistirem essa talk da Lea Verou que foi basicamente de onde eu extraí tudo para fazer esse post. Ela é incrível nessa talk, vale muito a pena =)