Criando uma entrada de intervalo personalizada que parece consistente em todos os navegadores
Publicados: 2022-03-10Como um dos mantenedores de uma biblioteca de componentes de interface do usuário, implementei e estilizei miríades de elementos de entrada. Um dia me foi atribuída a tarefa de adicionar uma entrada de intervalo à biblioteca e imaginei que seria um processo semelhante às outras entradas que eu havia implementado no passado. Essa suposição estava correta até que comecei a testar a entrada de intervalo em vários navegadores e rapidamente percebi que tinha muito mais trabalho em minhas mãos.
Depois de muita pesquisa, finalmente consegui identificar postagens de blog, artigos e tutoriais aprofundados suficientes para me ajudar a estilizar a entrada de intervalo para renderizar de forma consistente. Em vez de ter que pesquisar vários recursos, o objetivo por trás desta postagem do blog é fornecer um balcão único para aprender como estilizar adequadamente uma entrada de intervalo que parecerá consistente em todos os navegadores. É o artigo que eu gostaria de ter quando tive que fazer isso sozinho e espero que ajude a tornar esse processo mais rápido e fácil para você.
Anatomia de uma entrada de intervalo
A entrada de intervalo consiste em duas partes principais:
- Acompanhar
Esta é a parte do controle deslizante que o polegar corre ao longo. Ou dito de outra forma, é o elemento longo que representa os intervalos de valores que podem ser selecionados. - Dedão
Este é um elemento na pista que o usuário pode mover para selecionar valores de intervalo variados.
Se fosse uma equação matemática:
entrada de intervalo = faixa + polegar
A entrada de intervalo às vezes é chamada de "slider" e, no restante deste artigo, usarei esses termos de forma intercambiável.
Inconsistências do navegador
Para demonstrar por que precisamos de um tutorial sobre estilizar entradas de intervalo em primeiro lugar, veremos algumas capturas de tela da entrada de intervalo HTML padrão e como ela é renderizada nos quatro principais navegadores (Chrome, Firefox, Safari e Borda). Ou, se preferir, você pode ver esta demonstração do CodeSandbox em cada um dos respectivos navegadores para ver as inconsistências do navegador em toda a sua glória.
Observação: essas capturas de tela foram feitas em setembro de 2021 e podem estar sujeitas a alterações à medida que os respectivos navegadores são atualizados.
Vamos começar olhando para o Chrome que, na minha opinião, renderiza a versão mais amigável da entrada por padrão.
O Firefox é o próximo e parece diferente da entrada renderizada do Chrome. No Firefox, a altura da pista é um pouco menor. Por outro lado, a altura e a largura do polegar são maiores e não possuem a mesma cor de fundo azul que a versão do Chrome.
O controle deslizante do Safari está mais próximo da versão do Firefox, mas é, mais uma vez, ainda diferente. Desta vez, a faixa parece ter um efeito sombrio e, a altura do polegar e a largura são menores do que as versões do Chrome e do Firefox. Se você olhar de perto, também poderá ver que o polegar não está centralizado diretamente na pista, dando-lhe uma aparência não polida.
Por último, mas não menos importante, está o Edge que, agora que o Microsoft Edge é construído com base no Chromium, está muito mais alinhado com os outros três navegadores do que seu antecessor pré-Chromium. No entanto, podemos ver que ainda está renderizando de maneira diferente dos outros três navegadores. A versão do Edge de sua entrada de alcance é muito semelhante à versão do Chrome, exceto que tem uma cor de fundo cinza mais escura para o polegar e o lado esquerdo da faixa antes do polegar.
Agora que vimos o quão inconsistente cada navegador renderiza a entrada de intervalo, vamos dar uma olhada em como podemos usar CSS para uniformizá-los.
Redefinição de intervalo (estilos de linha de base)
Como as inconsistências do navegador variam muito, precisamos começar em condições equitativas. Uma vez que os estilos padrão que cada navegador aplica tenham sido removidos, podemos começar a trabalhar para fazer uma entrada de aparência mais uniforme. Usaremos o seletor de atributo de elemento input[type="range"]
e os estilos aplicados aqui atuarão como uma redefinição de CSS para a entrada.
Para aplicar os estilos de linha de base, precisamos de quatro propriedades:
-
-webkit-appearance: none;
Essa propriedade é um prefixo de fornecedor que se aplica a todos os principais navegadores. Ao atribuir o valornone
, isso informa a cada navegador respectivo para limpar todos os estilos padrão. Isso nos permite começar do zero e construir a aparência da entrada a partir desse ponto. -
background: transparent;
Isso limpa o plano de fundo padrão aplicado à entrada. -
cursor: pointer;
-
width
Define a largura geral da entrada.
input[type="range"] { -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; width: 15rem; }
Estilizando a pista
Ao estilizar a faixa (e o polegar), precisaremos direcionar os diferentes prefixos de fornecedores específicos dos navegadores para aplicar os estilos apropriados no elemento relevante. No futuro, qualquer pseudoelemento prefixado com -webkit
será aplicado aos navegadores Chrome, Safari, Opera e Edge (pós-Chromium). Qualquer coisa prefixada com -moz
pertence ao Firefox.
Abaixo estão os pseudo-elementos que usaremos para direcionar a faixa:
-
::-webkit-slider-runnable-track
Segmenta a faixa no Chrome, Safari e Edge Chromium. -
::-moz-range-track
Segmenta a faixa no Firefox.
/***** Track Styles *****/ /***** Chrome, Safari, Opera, and Edge Chromium *****/ input[type="range"]::-webkit-slider-runnable-track { background: #053a5f; height: 0.5rem; } /******** Firefox ********/ input[type="range"]::-moz-range-track { background: #053a5f; height: 0.5rem; }
As únicas propriedades necessárias para a trilha são a height
e o plano de background
. No entanto, é comum ver um border-radius
aplicado para arredondar as bordas.
Estilizando o polegar
Estilizar o polegar (o botão do meio que o usuário move) tem mais nuances que precisam ser consideradas, pois há mais inconsistências entre os navegadores nessa parte do intervalo de entrada.
Abaixo estão os pseudo-elementos que usaremos para direcionar o polegar:
-
::-webkit-slider-thumb
Tem como alvo o polegar no Chrome, Safari e Edge Chromium. -
::-moz-range-thumb
Tem como alvo o polegar no Firefox.
Como os navegadores Firefox e Webkit têm problemas de estilo diferentes, abordarei cada problema individualmente e demonstrarei como lidar com cada um dos padrões peculiares que são aplicados ao polegar.
Chrome, Safari, Edge Chromium (Webkit)
O primeiro estilo que precisamos aplicar ao pseudo-elemento ::-webkit-slider-thumb
é o -webkit-appearance: none;
prefixo do fornecedor. Usamos essa propriedade na seção "Estilos de linha de base" para substituir os estilos padrão gerais que são aplicados pelo navegador e serve a um propósito semelhante no thumb.
Depois que os estilos padrão forem removidos, podemos aplicar nossos próprios estilos personalizados. Supondo que aplicamos height
, width
e background-color
ao polegar, aqui está um exemplo do que teríamos até agora:
Por padrão, os navegadores WebKit renderizam a miniatura para que ela não fique centralizada na faixa.
Para centralizar corretamente o polegar na trilha, podemos usar a seguinte fórmula e aplicá-la à propriedade margin-top
:
margin-top = (altura da faixa em pixels / 2) - (altura do polegar em pixels /2)
Tomando os estilos que aplicamos nas seções anteriores e convertendo rems
em pixels, teríamos uma altura de trilha de 8px e uma altura de polegar de 32px. Isso significaria que:
margem superior = (8/2) - (32/2) = 4 - 16 = -12px
Com base nisso, nossos estilos finalizados para os navegadores do webkit seriam parecidos com o seguinte bloco de código:
/***** Thumb Styles *****/ /***** Chrome, Safari, Opera, and Edge Chromium *****/ input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; /* Override default look */ appearance: none; margin-top: -12px; /* Centers thumb on the track */ background-color: #5cd5eb; height: 2rem; width: 1rem; }
Raposa de fogo
Ao aplicar estilos ao polegar no Firefox, você precisará aproveitar o pseudo-elemento ::-moz-range-thumb
. Felizmente, o Firefox não sofre do mesmo problema de centralização que os navegadores Webkit. No entanto, é uma pegadinha em torno do raio da borda padrão e da borda cinza que se aplica ao polegar.
Para corrigir a borda cinza padrão, podemos adicionar a border: none;
propriedade. Para remover o border-radius padrão que é aplicado, podemos adicionar a propriedade border-radius: 0
e agora a miniatura parecerá consistente em todos os navegadores.
Com base nisso, nossos estilos finalizados para o navegador Firefox ficariam assim:
/***** Thumb Styles *****/ /***** Firefox *****/ input[type="range"]::-moz-range-thumb { border: none; /*Removes extra border that FF applies*/ border-radius: 0; /*Removes default border-radius that FF applies*/ background-color: #5cd5eb; height: 2rem; width: 1rem; }
Nota: Os navegadores do Webkit não aplicam automaticamente esse raio à borda, portanto, se você achar que deseja aplicar alguma forma de raio de borda ao polegar, em vez de cancelá-lo como fizemos acima, você precisará para aplicar as dimensões border-radius
desejadas aos pseudo-elementos -webkit-slider-thumb
e ::-moz-range-thumb
.
Estilos de foco
Como a entrada de intervalo é um elemento interativo, é imperativo adicionar estilos de foco para cumprir as melhores práticas e padrões de acessibilidade. Quando os estilos de foco são aplicados, ele fornece um indicador visual para os usuários e é especialmente importante para aqueles que usam um teclado para navegar em uma página.
De acordo com a documentação WAI-ARIA: Slider, é recomendado que:
O foco é colocado no controle deslizante (o objeto visual que o usuário do mouse moveria, também conhecido como polegar).
A primeira coisa que queremos fazer é remover os estilos de foco padrão para que possamos substituí-los por estilos personalizados. Para direcionar os estilos de foco thumbs, podemos aproveitar os pseudo-elementos ::-webkit-slider-thumb
e ::-moz-range-thumb
que usamos na seção anterior e combiná-los com a :focus
psuedo-class . Podemos então usar as propriedades CSS outline e outline-offset para estilizá-lo da maneira que queremos.
/***** Focus Styles *****/ /* Removes default focus */ input[type="range"]:focus { outline: none; } /***** Chrome, Safari, Opera, and Edge Chromium *****/ input[type="range"]:focus::-webkit-slider-thumb { border: 1px solid #053a5f; outline: 3px solid #053a5f; outline-offset: 0.125rem; } /******** Firefox ********/ input[type="range"]:focus::-moz-range-thumb { border: 1px solid #053a5f; outline: 3px solid #053a5f; outline-offset: 0.125rem; }
Nota : Se um border-radius
for aplicado à miniatura, o Firefox renderiza um contorno na forma da miniatura enquanto os outros navegadores exibem um contorno em bloco. Infelizmente, não há uma correção CSS simples para isso e é a única inconsistência que estará presente. No entanto, o objetivo principal de adicionar esses estilos é para fins de acessibilidade e o objetivo principal, fornecer um indicador visual quando o elemento é focado, ainda é alcançado.
Juntando tudo
Agora que cobrimos todos os estilos necessários para uniformizar a entrada de intervalo, veja como será a folha de estilo CSS final:
/********** Range Input Styles **********/ /*Range Reset*/ input[type="range"] { -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; width: 15rem; } /* Removes default focus */ input[type="range"]:focus { outline: none; } /***** Chrome, Safari, Opera and Edge Chromium styles *****/ /* slider track */ input[type="range"]::-webkit-slider-runnable-track { background-color: #053a5f; border-radius: 0.5rem; height: 0.5rem; } /* slider thumb */ input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; /* Override default look */ appearance: none; margin-top: -12px; /* Centers thumb on the track */ /*custom styles*/ background-color: #5cd5eb; height: 2rem; width: 1rem; } input[type="range"]:focus::-webkit-slider-thumb { border: 1px solid #053a5f; outline: 3px solid #053a5f; outline-offset: 0.125rem; } /******** Firefox styles ********/ /* slider track */ input[type="range"]::-moz-range-track { background-color: #053a5f; border-radius: 0.5rem; height: 0.5rem; } /* slider thumb */ input[type="range"]::-moz-range-thumb { border: none; /*Removes extra border that FF applies*/ border-radius: 0; /*Removes default border-radius that FF applies*/ /*custom styles*/ background-color: #5cd5eb; height: 2rem; width: 1rem; } input[type="range"]:focus::-moz-range-thumb { border: 1px solid #053a5f; outline: 3px solid #053a5f; outline-offset: 0.125rem; }
Conclusão
Além dos métodos descritos ao longo do artigo, você também pode aproveitar o gerador de CSS de entrada de intervalo que criei chamado range-input.css . O cerne deste projeto foi criar uma ferramenta que tornasse esse processo mais simples para os desenvolvedores. O gerador de CSS permite que você estilize rapidamente propriedades comuns de CSS e fornece um controle deslizante de demonstração que exibe uma visualização em tempo real dos estilos que você deseja aplicar.
Felizmente, as entradas de intervalo de estilo serão mais simples no futuro. No entanto, até esse dia chegar, saber quais pseudo-elementos e prefixos de fornecedores segmentar o ajudará a se preparar para estilizar controles deslizantes para atender às suas necessidades.
Mais recursos sobre a revista Smashing
- Geradores CSS
- Simplificando estilos de formulário com
accent-color
- Soluções CSS inteligentes para desafios comuns de interface do usuário
- Um mergulho profundo no
object-fit
ebackground-size
em CSS