Voltar

Meu primeiro desafio de Front-end

Redimensionando um carrossel sem alterar sua proporção
13/10/19   |   Vinícius Gomes
Front
Enquanto trabalhava na CJR, um grande desafio se colocou diante de mim. Um cliente, que trabalhava com produções audiovisuais, me pediu para desenvolver um carrossel que, além de responsivo, estivesse sempre na proporção 16 por 9.O meu ponto de partida foi um carrossel do framework Bootstrap 4. No entanto, eu precisava torná-lo responsivo e garantir que ele estivesse sempre na proporção desejada. Para solucionar esse problema, eu utilizei as Media Queries do CSS.
@media (max-width: 1199px) {
  :root {
    --carousel-width: 90vw;
  }
}
@media (min-width: 1200px) {
  :root {
    --carousel-width: 70vw;
  }
}
:root {
  --carousel-height: calc(var(--carousel-width) * 9 / 16);
}
.carousel, .carousel-inner, .carousel-item * {
  width: var(--carousel-width);
  height: var(--carousel-height);
}
Entretanto, essa solução não resolvia um grande problema: a largura da scrollbar do navegador.A scrollbar do navegador impôs duas dificuldades. Primeiro, ela ocupa espaço. Deste modo, eu precisava saber o tamanho dela para garantir que a proporção do carrossel estava correta. Segundo, a largura da scrollbar pode variar dependendo do navegador e do sistema operacional. Por exemplo, no momento da escrita desse artigo, a scrollbar do Google Chrome tem uma largura de: 17px no Windows 10, 15px no MacOS e 15px em sistemas Unix.A solução para o problema veio através de uma função em JavaScript que:
  1. Encontra a largura interna do navegador utilizando a função window.innerWidth(), pois ela ignora a presença da scrollbar;
  2. Encontra a largura interna usável do navegador utilizando o pseudoelemento :root, pois ele reconhece a presença da scrollbar;
  3. Compara os dois valores e salva a diferença em uma variável do CSS.
function setScrollbarWidth() {
  var element = document.querySelector(':root');
  var width = window.innerWidth - element.offsetWidth;
element.style.setProperty('--scrollbar-width', width + 'px');
}
setScrollbarWidth();
Com a largura da scrollbar em mãos, é possível calcular o valor exato para se manter a proporção.
@media (max-width: 1199px) {
  :root {
    --carousel-width: calc(90vw - var(--scrollbar-width));
  }
}
@media (min-width: 1200px) {
  :root {
    --carousel-width: calc(70vw - var(--scrollbar-width));
  }
}
:root {
  --carousel-height: calc(var(--carousel-width) * 9 / 16);
}
.carousel, .carousel-inner, .carousel-item * {
  width: var(--carousel-width);
  height: var(--carousel-height);
}
Desse modo, o carrossel está sempre seguindo a proporção 16:9. Entretanto, imagens que não seguem essa proporção aparecem distorcidas. Esse problema pode ser corrigido utilizando a propriedade object-fit do CSS.
.carousel-item {
  /* a cor preta no fundo ajuda a ver os controles */
  /* do carrossel quando a imagem é redimensionada */
  background-color: black;
}
.carousel-item * {
  object-fit: contain;
}
Com esse método, é possível incorporar vídeos ao carrossel também. Entretanto, pode ser necessário fazer algumas alterações no carrossel do Bootstrap para que os controles dele deixem de sobrepor os controles do player de vídeo.Dica: adicionar as classes ‘h-25’ e ‘my-auto’ aos controles é um solução simples e efetiva.
<a class="carousel-control-prev h-25 my-auto" href="" role="button" data-slide="prev">
  <span class="carousel-control-prev-icon" aria-hidden="true">
  </span>
  <span class="sr-only">Previous</span>
</a>

Sobre o autor:

Vinícius Gomes
Ex-membro

Oi, eu sou o Vinícius! Adoro um franguinho frito e assistir Cowboy Bebop ~