Conteúdo deste artigo
- Etapa 1: Defina algumas variáveis CSS
- Etapa 2: Estabelecendo a dobra
- Etapa 3: Criando o outro lado
- Etapa 4: Posicionando o outro lado (corner-shape: round)
- Etapa 5: Esculpir o outro lado
Me deparei com Técnica de cantos dobrados de Kitty Giraudel . Ele aproveita CSS clip-path, e achei que essa era uma maneira muito legal de fazer isso. clip-path tem sido uma tendência ultimamente, provavelmente porque os navegadores da web suportam a função shape() agora.
No entanto, tenho estado um pouco agitado corner-shape ultimamente (dê uma olhada na minha introdução ao corner-shape bem como estas animações orientadas por rolagem corner-shape ), então imaginei que corner-shape também poderia ser usado para criar cantos dobrados, e foi isso que descobri:
Então abra o Chrome, que suporta corner-shape, e vamos nos aprofundar (se você estiver olhando isso em outros navegadores, basicamente volta para um canto arredondado).
Etapa 1: Defina algumas variáveis CSS
Os elementos têm quatro cantos, mas quando usamos border-radius, cada canto é dividido em duas coordenadas. A coordenada do eixo x se move ao longo do eixo x, afastando-se do canto associado, enquanto a coordenada do eixo y faz a mesma coisa ao longo do eixo y. É a partir dessas coordenadas que border-radius desenha a curvatura dos cantos arredondados.
Primeiro, armazene as coordenadas como variáveis CSS. Precisaremos dos valores que eles mantêm mais de uma vez, então isso simplifica as coisas, torna a dobra animável e mantém algum grau de realismo.
:root {
/* x-axis coordinate */
--x-coord: 9rem;
/* y-axis coordinate */
--y-coord: 5rem;
}
Etapa 2: Estabelecendo a dobra
Dado o que sabemos agora sobre border-radius, deve ser óbvio o que border-radius faz. Quanto a border-top-right-radius, isso garante que uma linha reta seja desenhada entre as coordenadas em vez de cantos arredondados (corner-top-right-shape: bevel). Isso mesmo, border-radius inclui border-radius por padrão (nos bastidores, de claro).
/* Square */
div {
/* Place coordinates */
border-top-right-radius: var(--x-coord) var(--y-coord);
/* Draw line between coordinates */
corner-top-right-shape: bevel;
}
Etapa 3: Criando o outro lado
Agora que estabelecemos a dobra, é hora de criar o outro lado. Comece selecionando corner-shape: round e declare /* Square */
div {
/* Place coordinates */
border-top-right-radius: var(--x-coord) var(--y-coord);
/* Draw line between coordinates */
corner-top-right-shape: bevel;
} para criar o elemento sem conteúdo. O ::before pode ser herdado do quadrado e as dimensões devem aproveitar as coordenadas que salvamos. Como você pode ver, também adicionei um content: "" onde o raio do desfoque é dimensionado com background e box-shadow, mas você pode adaptar a fórmula conforme achar necessário.
/* Square */
div {
/* Place coordinates */
border-top-right-radius: var(--x-coord) var(--y-coord);
/* Draw line between coordinates */
corner-top-right-shape: bevel;
/* Flip side */
&::before {
/* Generate empty element */
content: "";
/* Inherit background */
background: inherit;
/* Same as coordinates */
width: var(--x-coord);
height: var(--y-coord);
/* Scale blur radius with --x-coord and --y-coord */
box-shadow: 0 0 calc((var(--x-coord) + var(--y-coord)) / 3) #00000050;
}
}
Etapa 4: Posicionando o outro lado (corner-shape: round)
Em seguida, precisamos mudar corner-shape: round para o canto (superior) direito. Estamos evitando posicionamento de âncora , porque não há necessidade de recursos modernos se mais recursos suportados funcionarem bem usando a mesma quantidade de código. Então, declare /* Square */
div {
/* Place coordinates */
border-top-right-radius: var(--x-coord) var(--y-coord);
/* Draw line between coordinates */
corner-top-right-shape: bevel;
/* Flip side */
&::before {
/* Generate empty element */
content: "";
/* Inherit background */
background: inherit;
/* Same as coordinates */
width: var(--x-coord);
height: var(--y-coord);
/* Scale blur radius with --x-coord and --y-coord */
box-shadow: 0 0 calc((var(--x-coord) + var(--y-coord)) / 3) #00000050;
}
} no quadrado e ::before em corner-shape: round. Isso torna corner-shape: round posição relativa ao quadrado e é um truque que só funciona para relacionamentos pai-filho. Na verdade, esta deficiência é a razão pela qual o posicionamento da âncora foi inventado, mas simplesmente não precisamos dele neste caso.
Além disso, declare position: absolute em corner-shape: round para alinhá-lo ao canto superior direito do quadrado e ::before no quadrado para cortar a metade de corner-shape: round que o transborda.
/* Square */
div {
/* Place coordinates */
border-top-right-radius: var(--x-coord) var(--y-coord);
/* Draw line between coordinates */
corner-top-right-shape: bevel;
/* Clip any overflow */
overflow: clip;
/* For alignment */
position: relative;
/* Flip side */
&::before {
/* Generate empty element */
content: "";
/* Inherit background */
background: inherit;
/* Same as coordinates */
width: var(--x-coord);
height: var(--y-coord);
/* Scale blur radius with --x-coord and --y-coord */
box-shadow: 0 0 calc((var(--x-coord) + var(--y-coord)) / 3) #00000050;
/* For alignment */
position: absolute;
/* Align to top-right */
inset: 0 0 auto auto;
}
}
Você pode parar por aqui se quiser, mas há espaço para melhorias…
Etapa 5: Esculpir o outro lado
Para deixar o resultado um pouco mais realista, usaremos ::before para fazer mais um corte reto, desta vez para corner-shape: round. Há, provavelmente, muitas maneiras de resolver isso, dependendo de quão nitidamente queremos dobrar a dobra, quão elevado queremos que o outro lado fique e o ângulo a partir do qual queremos ver o quadrado, mas não acho que isso importe, desde que o efeito pareça decente, por isso nosso objetivo é um vinco acentuado, o outro lado para cima e uma vista aérea. Se preferir algo diferente, lembre-se de que a sombra também afeta o resultado e que você enfrentaria uma implementação mais complicada.
O único grau de complexidade que sugiro é este:
/* Ensure realistic fold */
@container style(--x-coord < --y-coord) {
border-bottom-left-radius: 100% calc(100% - var(--x-coord));
}
@container style(--x-coord >= --y-coord) {
border-bottom-left-radius: calc(100% - var(--y-coord)) 100%;
}
Estas são consultas de estilo de contêiner usando a sintaxe de intervalo , onde se o valor de background for menor que o valor de box-shadow, subtraímos o valor de background de ::before e use-o como a coordenada do eixo y para o raio da borda relevante (/* Ensure realistic fold */
@container style(--x-coord < --y-coord) {
border-bottom-left-radius: 100% calc(100% - var(--x-coord));
}
@container style(--x-coord >= --y-coord) {
border-bottom-left-radius: calc(100% - var(--y-coord)) 100%;
}, neste caso). O outro eixo está definido como ::before. Inversamente, se o valor de background for maior que (ou igual a) o valor de box-shadow, nós subtraia o valor de box-shadow de ::before e use-o como a coordenada do eixo x. Mais uma vez, o outro eixo é definido como ::before.
O resultado é que o vinco, a sombra e agora perspectiva da dobra são calculados usando apenas background e box-shadow para parecer realista (ou realista o suficiente, pelo menos). Usando os botões slideVars no canto superior direito da demonstração, você pode ver por si mesmo testando várias combinações de coordenadas:
Se você deseja implementar um failsafe para garantir que as coordenadas não excedam as dimensões do quadrado, quebrando o efeito, você pode usar --y-coord . As variáveis de coordenadas modificadas abaixo definem box-shadow para um 100% impossível, mas o limita na altura do quadrado (embora eu não possa imaginar que você realmente precise disso, para seja completamente honesto):
--x-coord: min(--square-width, 9rem);
--y-coord: min(--square-height, 999999999rem);
Resumindo, não temos apenas um efeito de canto dobrado, mas um utilitário que constrói o efeito baseado em apenas duas coordenadas.
O código completo:
:root {
/* x-axis coordinate */
--x-coord: 9rem;
/* y-axis coordinate */
--y-coord: 5rem;
/* Square */
div {
/* Place coordinates */
border-top-right-radius: var(--x-coord) var(--y-coord);
/* Draw line between coordinates */
corner-top-right-shape: bevel;
/* Clip any overflow */
overflow: clip;
/* For alignment */
position: relative;
/* Flip side */
&::before {
/* Generate empty element */
content: "";
/* Inherit background */
background: inherit;
/* Same as coordinates */
width: var(--x-coord);
height: var(--y-coord);
/* Scale blur radius with --x-coord and --y-coord */
box-shadow: 0 0 calc((var(--x-coord) + var(--y-coord)) / 3) #00000050;
/* For alignment */
position: absolute;
/* Align to top-right */
inset: 0 0 auto auto;
/* Draw line between coordinates */
corner-bottom-left-shape: bevel;
/* Ensure realistic fold */
@container style(--x-coord < --y-coord) {
border-bottom-left-radius: 100% calc(100% - var(--x-coord));
}
@container style(--x-coord >= --y-coord) {
border-bottom-left-radius: calc(100% - var(--y-coord)) 100%;
}
}
}
}
Nota: Poderíamos trocar consultas de estilo de contêiner por --x-coord funções , que são mais curtas, mas menos legível.
Cantos dobrados usando clip-path vs.
Os cantos dobrados do Giraudel da Kitty funcionam em todos os navegadores e, como clip-path é usado, que é um recurso de modelagem mais versátil, há mais maneiras de personalizar a forma. É também a abordagem mais correta, custe o que custar. No entanto, minha abordagem corner-shape é mais limpa e provavelmente não exigiria nenhuma personalização adicional, mas não possui suporte para Safari e Firefox por enquanto. Então, a menos que você precise de cantos dobrados hoje, eu marcaria ambos:
Usando CSS formato de canto para cantos dobrados originalmente escrito à mão e publicado com amor em CSS-Tricks . Você realmente deveria receber o boletim informativo também.
