Carregadores de elemento único: indo para 3D! Inteligência de dados PlatoBlockchain. Pesquisa vertical. Ai.

Carregadores de elemento único: indo para 3D!

Para este quarto e último artigo do nosso pequenas séries sobre carregadores de elemento único, vamos explorar padrões 3D. Ao criar um elemento 3D, é difícil imaginar que apenas um elemento HTML seja suficiente para simular algo como todas as seis faces de um cubo. Mas talvez possamos conseguir algo mais cúbicocomo em vez disso, mostrando apenas os três lados frontais da forma - é totalmente possível e é isso que faremos juntos.

Série de artigos

O carregador de cubo dividido

Aqui está um carregador 3D onde um cubo é dividido em duas partes, mas é feito apenas com um único elemento:

Retorno de Incorporação do CodePen

Cada metade do cubo é feita usando um pseudoelemento:

Carregadores de elemento único: indo para 3D! Inteligência de dados PlatoBlockchain. Pesquisa vertical. Ai.
Carregadores de elemento único: indo para 3D!

Legal certo?! Podemos usar um gradiente cônico com CSS clip-path no elemento ::before e ::after pseudos para simular as três faces visíveis de um cubo 3D. A margem negativa é o que une os dois pseudos para se sobreporem e simularem um cubo completo. O resto do nosso trabalho consiste principalmente em animar essas duas metades para obter carregadores bonitos!

Vamos dar uma olhada em um visual que explica a matemática por trás dos pontos do clip-path usados ​​para criar este elemento semelhante a um cubo:

Carregadores de elemento único: indo para 3D! Inteligência de dados PlatoBlockchain. Pesquisa vertical. Ai.
Carregadores de elemento único: indo para 3D!

Temos nossas variáveis ​​e uma equação, então vamos colocá-las para funcionar. Primeiro, vamos estabelecer nossas variáveis ​​e definir o dimensionamento para o principal .loader elemento:

.loader { --s: 150px; /* control the size */ --_d: calc(0.353 * var(--s)); /* 0.353 = sin(45deg)/2 */ width: calc(var(--s) + var(--_d)); aspect-ratio: 1; display: flex;
}

Nada muito louco até agora. Nós temos uma 150px quadrado configurado como um contêiner flexível. Agora estabelecemos nossos pseudos:

.loader::before,
.loader::after { content: ""; flex: 1;
}

São duas metades do .loader recipiente. Precisamos pintá-los, então é aí que o nosso gradiente cônico entra em ação:

.loader::before,
.loader::after { content: ""; flex: 1; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0);
}

O gradiente está lá, mas parece estranho. Precisamos prenda-o ao elemento:

.loader::before,
.loader::after { content: ""; flex: 1; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0); clip-path: polygon(var(--_d) 0, 100% 0, 100% calc(100% - var(--_d)), calc(100% - var(--_d)) 100%, 0 100%, 0 var(--_d));
}

Vamos ter certeza de que as duas metades se sobrepõem com um margem negativa:

.loader::before { margin-right: calc(var(--_d) / -2);
} .loader::after { margin-left: calc(var(--_d) / -2);
}

Agora vamos fazê-los se mover!

.loader::before,
.loader::after { /* same as before */ animation: load 1.5s infinite cubic-bezier(0, .5, .5, 1.8) alternate;
} .loader::after { /* same as before */ animation-delay: -.75s
} @keyframes load{ 0%, 40% { transform: translateY(calc(var(--s) / -4)) } 60%, 100% { transform: translateY(calc(var(--s) / 4)) }
}

Aqui está a demonstração final mais uma vez:

Retorno de Incorporação do CodePen

O carregador de cubo de progresso

Vamos usar a mesma técnica para criar um carregador de progresso 3D. Sim, ainda apenas um elemento!

Retorno de Incorporação do CodePen

Não estamos mudando nada no que diz respeito à simulação do cubo da mesma forma que fizemos antes, a não ser alterar a altura e a proporção do carregador. A animação que estamos fazendo depende de uma técnica surpreendentemente fácil onde atualizamos a largura do lado esquerdo enquanto o lado direito preenche o espaço restante, graças a flex-grow: 1.

O primeiro passo é adicionar alguma transparência ao lado direito usando opacity:

Retorno de Incorporação do CodePen

Isso simula o efeito de que um lado do cubo está preenchido enquanto o outro está vazio. Em seguida, atualizamos a cor do lado esquerdo. Para fazer isso, atualizamos as três cores dentro do gradiente cônico ou adicionamos uma cor de fundo com um background-blend-mode:

.loader::before { background-color: #CC333F; /* control the color here */ background-blend-mode: multiply;
}

Este truque só nos permite atualizar a cor uma vez. O lado direito do carregador combina com os três tons de branco do gradiente cônico para criar três novos tons da nossa cor, mesmo que estejamos usando apenas um valor de cor. Truque de cores!

Retorno de Incorporação do CodePen

Vamos animar a largura do lado esquerdo do carregador:

Retorno de Incorporação do CodePen

Ops, a animação é um pouco estranha no começo! Observe como isso começa fora do cubo? Isso ocorre porque estamos iniciando a animação no 0% largura. Mas devido ao clip-path e margem negativa que estamos usando, o que precisamos fazer é começar do nosso --_d variável, que usamos para definir o clip-path pontos e a margem negativa:

@keyframes load { 0%, 5% {width: var(--_d); } 95%, 100% {width: 100%; }
}

Isso é um pouco melhor:

Retorno de Incorporação do CodePen

Mas podemos tornar esta animação ainda mais suave. Você notou que está faltando alguma coisinha? Deixe-me mostrar uma captura de tela para comparar a aparência da demonstração final com a última demonstração:

Carregadores de elemento único: indo para 3D! Inteligência de dados PlatoBlockchain. Pesquisa vertical. Ai.

É a face inferior do cubo! Como o segundo elemento é transparente, precisamos ver a face inferior desse retângulo, como você pode ver no exemplo à esquerda. É sutil, mas deveria estar lá!

Podemos adicionar um gradiente ao elemento principal e recortá-lo como fizemos com os pseudos:

background: linear-gradient(#fff1 0 0) bottom / 100% var(--_d) no-repeat;

Aqui está o código completo depois que tudo estiver reunido:

.loader { --s: 100px; /* control the size */ --_d: calc(0.353*var(--s)); /* 0.353 = sin(45deg) / 2 */ height: var(--s); aspect-ratio: 3; display: flex; background: linear-gradient(#fff1 0 0) bottom / 100% var(--_d) no-repeat; clip-path: polygon(var(--_d) 0, 100% 0, 100% calc(100% - var(--_d)), calc(100% - var(--_d)) 100%, 0 100%, 0 var(--_d));
}
.loader::before,
.loader::after { content: ""; clip-path: inherit; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0);
}
.loader::before { background-color: #CC333F; /* control the color here */ background-blend-mode: multiply; margin-right: calc(var(--_d) / -2); animation: load 2.5s infinite linear;
}
.loader:after { flex: 1; margin-left: calc(var(--_d) / -2); opacity: 0.4;
} @keyframes load { 0%, 5% { width: var(--_d); } 95%, 100% { width: 100%; }
}
Retorno de Incorporação do CodePen

É isso! Acabamos de usar uma técnica inteligente que usa pseudoelementos, gradientes cônicos, recorte, mesclagem de fundo e margens negativas para obter, não um, mas dois carregadores 3D de aparência atraente com nada mais do que um único elemento na marcação.

Mais 3D

Ainda podemos ir mais longe e simular um número infinito de cubos 3D usando um elemento — sim, é possível! Aqui está uma grade de cubos:

Retorno de Incorporação do CodePen

Esta demonstração e as seguintes demonstrações não são suportadas no Safari no momento em que este artigo foi escrito.

Louco, certo? Agora estamos criando um padrão repetido de cubos feitos usando um único elemento… e sem pseudos também! Não vou entrar em detalhes sobre a matemática que estamos usando (há números muito específicos lá), mas aqui está uma figura para visualizar como chegamos aqui:

Carregadores de elemento único: indo para 3D! Inteligência de dados PlatoBlockchain. Pesquisa vertical. Ai.
Carregadores de elemento único: indo para 3D!

Primeiro usamos um conic-gradient para criar o padrão de cubo repetido. A repetição do padrão é controlada por três variáveis:

  • --size: Fiel ao seu nome, controla o tamanho de cada cubo.
  • --m: Isso representa o número de colunas.
  • --n: Este é o número de linhas.
  • --gap: esta é a lacuna ou distância entre os cubos
.cube { --size: 40px; --m: 4; --n: 5; --gap :10px; aspect-ratio: var(--m) / var(--n); width: calc(var(--m) * (1.353 * var(--size) + var(--gap))); background: conic-gradient(from -90deg at var(--size) calc(0.353 * var(--size)), #249FAB 135deg, #81C5A3 0 270deg, #26609D 0) /* update the colors here */ 0 0 / calc(100% / var(--m)) calc(100% / var(--n));
}

Em seguida, aplicamos uma camada de máscara usando outro padrão do mesmo tamanho. Esta é a parte mais complicada desta ideia. Usando uma combinação de um linear-gradient e de um conic-gradient cortaremos algumas partes do nosso elemento para manter apenas as formas do cubo visíveis.

.cube { /* etc. */ mask: linear-gradient(to bottom right, #0000 calc(0.25 * var(--size)), #000 0 calc(100% - calc(0.25 * var(--size)) - 1.414 * var(--gap)), #0000 0), conic-gradient(from -90deg at right var(--gap) bottom var(--gap), #000 90deg, #0000 0); mask-size: calc(100% / var(--m)) calc(100% / var(--n)); mask-composite: intersect;
}

O código pode parecer um pouco complexo, mas graças às variáveis ​​CSS tudo o que precisamos fazer é atualizar alguns valores para controlar nossa matriz de cubos. Precisa de uma grade 10×10? Atualize o --m e --n variáveis ​​para 10. Precisa de uma lacuna maior entre os cubos? Atualize o --gap valor. Os valores das cores são usados ​​apenas uma vez, então atualize-os para uma nova paleta de cores!

Agora que temos outra técnica 3D, vamos usá-la para construir variações do carregador brincando com diferentes animações. Por exemplo, que tal um padrão repetido de cubos deslizando infinitamente da esquerda para a direita?

Retorno de Incorporação do CodePen

Este carregador define quatro cubos em uma única linha. Isso significa que nosso --n valor é 4 e --m é igual a 1 . Em outras palavras, não precisamos mais disso!

Em vez disso, podemos trabalhar com o --size e --gap variáveis ​​em um contêiner de grade:

.loader { --size: 70px; --gap: 15px; width: calc(3 * (1.353 * var(--size) + var(--gap))); display: grid; aspect-ratio: 3;
}

Este é o nosso contêiner. Temos quatro cubos, mas queremos mostrar apenas três no recipiente de cada vez, para que sempre tenhamos um deslizando para dentro enquanto outro desliza para fora. É por isso que estamos fatorando a largura por 3 e ter a proporção definida como 3 tão bem.

Vamos ter certeza de que nosso padrão de cubo está configurado para a largura de quatro cubos. Faremos isso no contêiner ::before pseudo-elemento:

.loader::before { content: ""; width: calc(4 * 100% / 3); /* Code to create four cubes */
}

Agora que temos quatro cubos em um contêiner de três cubos, podemos justificar o padrão do cubo no final do contêiner de grade para estourá-lo, mostrando os três últimos cubos:

.loader { /* same as before */ justify-content: end;
}

Aqui está o que temos até agora, com um contorno vermelho para mostrar os limites do contêiner da grade:

Retorno de Incorporação do CodePen

Agora tudo o que precisamos fazer é mover o pseudoelemento para a direita adicionando nossa animação:

@keyframes load { to { transform: translate(calc(100% / 4)); }
}
Retorno de Incorporação do CodePen

Você entendeu o truque da animação? Vamos terminar ocultando o padrão de cubo transbordante e adicionando um toque de máscara para criar aquele efeito de esmaecimento no início e no fim:

.loader { --size: 70px; --gap: 15px; width: calc(3*(1.353*var(--s) + var(--g))); display: grid; justify-items: end; aspect-ratio: 3; overflow: hidden; mask: linear-gradient(90deg, #0000, #000 30px calc(100% - 30px), #0000);
}
Retorno de Incorporação do CodePen

Podemos tornar isso muito mais flexível introduzindo uma variável, --n, para definir quantos cubos serão exibidos no contêiner de uma só vez. E como o número total de cubos no padrão deve ser um a mais que --n, podemos expressar isso como calc(var(--n) + 1).

Aqui está a coisa completa:

Retorno de Incorporação do CodePen

OK, mais um carregador 3D semelhante, mas com os cubos mudando de cor em sucessão em vez de deslizarem:

Retorno de Incorporação do CodePen

Vamos contar com um fundo animado com background-blend-mode para este:

.loader { /* ... */ background: linear-gradient(#ff1818 0 0) 0% / calc(100% / 3) 100% no-repeat, /* ... */; background-blend-mode: multiply; /* ... */ animation: load steps(3) 1.5s infinite;
}
@keyframes load { to { background-position: 150%; }
}

Removi o código supérfluo usado para criar o mesmo layout do último exemplo, mas com três cubos em vez de quatro. O que estou adicionando aqui é um gradiente definido com uma cor específica que combina com o gradiente cônico, assim como fizemos anteriormente para o carregador 3D da barra de progresso.

A partir daí, está animando o gradiente do fundo background-position como uma animação de três etapas para fazer os cubos piscarem em cores, um de cada vez.

Se você não estiver familiarizado com os valores que estou usando para background-position e a sintaxe de fundo, eu recomendo fortemente um dos meus artigos anteriores e um de minhas respostas do Stack Overflow. Você encontrará uma explicação muito detalhada lá.

Podemos atualizar o número de cubos para torná-lo variável?

Sim, eu tenho um solução para isso, mas gostaria que você desse uma olhada em vez de incorporá-lo aqui. Pegue o que aprendemos no exemplo anterior e tente fazer o mesmo com este — depois compartilhe seu trabalho nos comentários!

Variações em abundância!

Assim como os outros três artigos desta série, gostaria de deixar você com alguma inspiração para seguir em frente e criar seus próprios carregadores. Aqui está uma coleção que inclui os carregadores 3D que fizemos juntos, além de alguns outros para dar asas à sua imaginação:

Retorno de Incorporação do CodePen

Isso é um envoltório

Espero que você tenha gostado de passar algum tempo criando carregadores de elemento único comigo nas últimas semanas. É uma loucura termos começado com um spinner aparentemente simples e, gradualmente, adicionado novas peças para chegarmos a técnicas 3D que ainda usam apenas um único elemento na marcação. É exatamente assim que o CSS se parece quando aproveitamos seus poderes: escalonável, flexível e reutilizável.

Obrigado novamente por ler esta pequena série! Vou encerrar lembrando que tenho um coleção de mais de 500 carregadeiras se você está procurando mais ideias e inspiração.

Série de artigos


Carregadores de elemento único: indo para 3D! publicado originalmente em Truques de CSS. Você deve receba o boletim informativo.

Carimbo de hora:

Mais de Truques CSS