CSS

10 jan, 2013

Feliz Ano Novo com HTML5, CSS3 e uma pitada de SVG – Parte 01

Publicidade

Em dezembro passado, o Bernard De Luna lançou, aqui no iMasters, um desafio CSS com tema livre. Em reconhecimento à participação do Bernard nos inúmeros desafios CSS que lancei em meu blog e à sua disposição em “abraçar a causa” dos desafios CSS, resolvi desenvolver um tema, não para participar do desafio, mas antes de tudo para homenagear e agradecer ao Bernard.

Falarei um pouco sobre o tema que desenvolvi, na esperança de que as funcionalidades aplicadas sirvam como fonte de aprendizado, base para estudos e motivação para criações mais sofisticadas.

Quero ressaltar que a finalidade do tema é exclusivamente a descrita no parágrafo anterior. Não está em questão o design, a aplicação prática, a acessibilidade e outras questões que obviamente podem ser melhoradas, pois elas não são o foco do tema.

Antes de continuar a leitura, solicito que você visualize o tema desenvolvido, para melhor acompanhar a sequência da explicação. O tema está hospedado em: tema do Maujor (abre em nova janela) e vou supor que você já o tenha visualizado e ele permaneça aberto em outra janela para eventuais consultas durante a leitura.

Tema e suas funcionalidades

Conforme observado, o tema foi desenvolvido com a finalidade principal de demonstrar a possibilidade de se criar animações com CSS3 e as funcionalidades aplicadas no seu desenvolvimento, em resumo, foram as seguintes:

HTML5

  • Estrutura geral da marcação;
  • Elementos progress e marquee.

CSS

  • Propriedades de posicionamento, dimensionamento e estilização geral das CSS2;
  • Funcionalidades de media queries;
  • Sombras, opacidade e bordas arredondadas das CSS3;
  • Gradientes e box-sizing das CSS3;
  • Transformações e animações das CSS3.

SVG

  • Elementos svg, defs, circle, pattern, use e rect;
  • Funcionalidade href:xlink.

Descrição geral da marcação

Além dos novos elementos progress e marquee da HTML5 e o elemento svg da SVG, todos os demais boxes foram marcados com elementos da HTML e aparecem na marcação na ordem mostrada a seguir:

  1. Elemento svg para criar o bandô da cortina no topo da página;
  2. Elemento h1.amocss container para “Eu ♥ CSS”;
  3. Elemento progress para a barra de progresso inicial;
  4. Elemento p.navegadores container para “Ver no Firefox, Chrome ou IE10”;
  5. Elemento marquee para a mensagem, final de recarregamento da página;
  6. Elemento div.cortina.cesquerda para a cortina à esquerda;
  7. Elemento div.cortina.cdireita para a cortina à direita;
  8. Elemento div.palco container geral dos demais boxes da marcação que se seguem;
  9. Elemento div.astros container para as estrelas no céu;
  10. Elemento div.dia container para o gradiente de fundo do dia;
  11. Elemento div.noite container para o gradiente de fundo da noite;
  12. Elemento span.rojão container para a subida do rojão;
  13. Elemento div.fireworks container para a explosão do rojão;
  14. Elemento div.edificios container para os edifícios;
  15. Elemento div.container-lua container para a lua;
  16. Elemento div.sol container para o sol;
  17. Elemento div.anos container para os anos 2012 e 2013;
  18. Elemento h2 container para “Feliz Ano Novo”.

Suporte nos navegadores

O tema foi desenvolvido e testado para funcionar nos navegadores Firefox, Chrome (versões mais recentes) e Internet Explorer 10. O navegador Opera, por suportar parcialmente gradientes e transformações 2D, renderiza inconsistentemente o tema. O navegador Safari, em ambiente Windows, apresenta pequenas incosistências, mas renderiza bem o tema. A renderização completa do tema foi obtida no navegador Firefox.

Nas folhas de estilos que mostraremos, algumas propriedades CSS3, tais como box-sizing, repeating-linear-gradient e outras, foram implementadas com uso de prefixos proprietários, pois as especificações ainda estão em fase de estudos no W3C.

Regras CSS gerais

Optei por não usar CSS reset, pois a quantidade de elementos usada na marcação é mínima e o reset foi declarado individualmente quando aplicável. Contudo, é bom conhecer a priori as definições de estilos para os elementos html e body. São elas:

CSS

html, body {   
  width: 100%; 
  height: 100%;   
}
body { 
  font: 100% sans-serif;
  background: black;
  color: white;
  margin: 0;
  padding-top: 20px;
  overflow: hidden;
  moz-box-sizing: border-box; 
  -webkit-box-sizing: border-box;
  -ms-box-sizing: border-box;
}

Código comentado: Declarar width e height igual a 100% para os elementos htm e body permite que se estenda qualquer container por toda a altura da janela com a declaração height: 100%;.

A declaração overflow: hidden destina-se a eliminar o aparecimento de barras de rolagem quando animamos elementos para fora da janela.

A declaração padding-top: 20px abre espaço para inserção do bandô da cortina no topo da janela como explicado no próximo item.

No Box Model CSS às dimensões finais do box são o resultado da soma da largura e altura (width e height) declaradas nas CSS com a espessura de border e padding declarados. A propriedade box-sizing com o valor border-box inclui a espessura de border e/ou padding na largura total dos boxes.

Carregamento da página

Ao terminar o carregamento da página, uma barra de progresso da HTML5 desloca-se na horizontal no topo da página com a finalidade de informar ao usuário que algo está para acontecer, dando-lhe tempo para visualizar a cortina.

O código que movimenta a barra de progresso é mostrado a seguir:

CSS

progress {
  position: absolute;
  z-index: 200;
  top: 22px;
  right: 120%; 
  width: 200px;
  height: 20px;
}

/* anima barra de progresso */
@-webkit-keyframes oprogress {
	0% { right: 120%; }	
	100% { right: -120%; }
}
@keyframes oprogress {
	0% { right: 120%; }	
	100% { right: -120%; }
}
progress { 
	animation: oprogress 18s;
	-webkit-animation: oprogress 18s;
	-ms-animation: oprogress 18s;
}

HTML

  <progress max="10" value="8"></progress>

Código comentado: Com declarações CSS posicionamos a barra de progresso 2px abaixo do bandô (top: 22px) da cortina e fora da tela à esquerda (right: 120%).

A animação da barra de progresso é feita com uso de @keyframes e uma função que foi denominada oprogress. O tempo de duração da animação é de 18s. Esse tempo coloca a barra de progresso a vista com retardo suficiente (progredir de right: -120% até right: 100%) para o usuário visualizar a interface inicial. O cálculo desse tempo é rapidamente obtido por experimentação. Alternativamente poderíamos usar a definição de um tempo de retardo como parâmetro da função oprogress e aproximar mais a barra da lateral esquerda da janela (right: -105%). O importante a notar é que a sincronização final foi obtida por experimentação.

Lembro que a sintaxe geral para definir uma animação denominada nome-da-função de um seletor CSS é a seguinte:

CSS

@keyframes nome-da-função {
    0% { propriedade: valor inicial; }
    50% { propriedade: valor intermediário; }
    100% { propriedade: valor final; }
}

seletor { nome-da-função duração função-timing delay repetições direção;  }

Onde:

  • nome-da-função: é um nome qualquer escolhido pelo autor para designar a animação;
  • duração: é o tempo, em segundos, de duração dea animação;
  • função-time: e uma função padrão que determina o progresso da animação no tempo;
  • delay: é o tempo, em segundos, para início da animação;
  • repetições: é o número de repetições da animação;
  • direção: anima cada ciclo no mesmo sentido ou em sentido inverso.

Bandô da cortina

O bandô da cortina foi criado com SVG conforme código mostrado a seguir:

1. <svg xmlns="http://www.w3.org/2000/svg" version="1.1" 
xmlns:xlink="http://www.w3.org/1999/xlink">
2. <style type="text/css"><![CDATA[
3.   svg {
4.     width: 2000px; 
5.     height: 20px; 
6.     background: black;
7.     position: absolute;
8.     top: 0; 
9.     left: 50%;
10.     margin-left: -1000px;
11.     z-index: 500;
12.   }
13. @media (max-width: 480px) {
14.  svg {transform: scale(.5);}
15. }
16. @media (min-width: 481px) and (max-width: 768px) {
17.  svg {transform: scale(.7);}
18. }
19. ]]></style>

20. <defs>
21.   <circle id="C" cx="10" cy="10" r="6" stroke="red" stroke-width="8" 
22.   stroke-dasharray="2, 1" fill="red"/>
23. </defs>
24. <pattern id="P" patternUnits="userSpaceOnUse" width="30" height="20">
25.   <use xlink:href="#C"/>
26. </pattern>
27. <rect x="0" y="0" width="2000" height="20" fill="black"/> 
28. <rect x="0" y="0" width="2000" height="20" fill="url(#P)"/> 
29. </svg>

Esse código SVG cria uma imagem vetorial conforme mostrada a seguir:

123

Código comentado

Linha(s) Descrição
1 e 29 A HTML5 permite que você insira o elemento <svg></svg> diretamente na marcação. Esse elemento é o container geral para a marcação XML necessária à criação de gráficos vetoriais SVG
2 e19 A estilização dos elementos SVG faz-se com folhas de estilo CSS exatamente como na marcação HTML. No exemplo usei uma folha de estilo incorporada. Notar a presença da seção CDATA para prevenir erros de parseamento de entidades HTML, tal como a presença, na folha de estilos, do sinal de combinação > para seletores filho.
3 a 12 Regras de estilos para o container do gráfico SVG. Define as dimensões, posicionamento e a cor de fundo do container. Notar que o comprimento total do bandô atende a resoluções de tela até 2000px e foi posicionado no topo da tela e centrado.
13 a 18 Escala o bandô responsivamente, com uso de media query.
20 e 23 Elemento defs container de uma engrenagem vermelha do bandô, criada conforme descrição a seguir. Esse elemento define um gráfico para uso posterior e não permite sua renderização.
21 e 22 Elemento circle cria um círculo na cor vermelha (fill="red") com centro em 10px, 10px (cx="10" cy="10") e raio 6px (r="6"). Adiciona uma borda de 8px (stroke-width="8") na cor vermelha (stroke="red") e traceja a bordade 2px em 2px separados por 1px. (stroke-dasharray="2, 1"). O atribudo id="C" é uma referência para uso da engrenagem repetidamente na horizontal.
Nota: Em SVG as bordas são aplicadas com metade da espessura para dentro e metade para fora da forma. Assim ao raio de 6px soma-se 8/2=4px para fora perfazendo um raio total de 10px.
24 e 26 Define um padrão a ser usado como preenchimento de uma forma. No nosso caso usaremos uma engrenagem para preencher um retângulo de 2000px x 20px repetidamente na horizontal. Notar que width="30" e height="20" para uma engrenagem de 20px x 20px faz com que ela se repita na horizontal e com 10px de espaçamento.
25 O elemento use linca para o gráfico a ser usado como padrão de preenchimento, no nosso caso a engrenagem.
27 Cria um retângulo de 2000px x 20px com fundo na cor preta.
28 Cria um retângulo de 2000px x 20px com fundo com o padrão (engrenagens) e sobrepões ao retângulo anterior, compondo engrenagens repetidas em fundo preto.

Cortina

As duas folhas da cortina foram criadas com dois elementos div flutuados à esquerda e a direita, respectivamente, conforme o código mostrado a seguir:

CSS

.cortina { /* cortinas */
  position: relative;
  z-index: 100;
  width: 50%;
  min-height: 100%;
  border-bottom: 10px dashed #444;
  box-sizing: border-box;
  -moz-box-sizing: border-box; 
  -webkit-box-sizing: border-box;
  -ms-box-sizing: border-box;
}
.cesquerda { /* cortina esquerda */ 
  float: left; 
  background: red; /* fallback */ 
  background: -moz-repeating-linear-gradient( left, black, red 4%, black 8% ); 
  background: -webkit-repeating-linear-gradient( left, black, red 4%, black 8% ); 
  background: -ms-repeating-linear-gradient( left, black, red 4%, black 8% ); 
  border-left: 1px solid black;
}
.cdireita { /* cortina direita */ 
  float: right; 
  background: red;  /* fallback */  
  background: -moz-repeating-linear-gradient( left, red, black 4%, red 8% );
  background: -webkit-repeating-linear-gradient( left, red, black 4%, red 8% );
  background: -ms-repeating-linear-gradient( left, red, black 4%, red 8% ); 
  border-right: 1px solid black;
}

/* abre cortina esquerda */
@-webkit-keyframes abrircesquerda {
	0% { margin-left: 0; }	
	10% { margin-left: -50%; }
	50% { margin-left: -500%; }
	80% { margin-left: 0; }	
	100% { margin-left: 0; }	
}
@keyframes abrircesquerda {
	0% { margin-left: 0; }	
	10% { margin-left: -50%; }
	50% { margin-left: -500%; }
	80% { margin-left: 0; }	
	100% { margin-left: 0; }	
}
.cesquerda { 
	animation: abrircesquerda 55s 6s;
	-webkit-animation: abrircesquerda 55s 6s;
	-ms-animation: abrircesquerda 55s 6s;
}
/* abre cortina direita */
@-webkit-keyframes abrircdireita {
	0% { margin-right: 0; }	
	10% { margin-right: -50%; }
	50% { margin-right: -500%; }
	80% { margin-right: 0; }	
	100% { margin-right: 0; }	
}
@keyframes abrircdireita {
	0% { margin-right: 0; }	
	10% { margin-right: -50%; }
	50% { margin-right: -500%; }
	80% { margin-right: 0; }	
	100% { margin-right: 0; }	
}
.cdireita { 
	animation: abrircdireita 55s 6s;
	-webkit-animation: abrircdireita 55s 6s;
	-ms-animation: abrircdireita 55s 6s;
}

HTML

<div></div>
<div></div>

Esse código cria a cortina conforme é mostrado a seguir:

2

Código comentado: A declaração da classe cortina para os dois elementos div que marcam as duas folhas da cortina permite estabelecer as regras CSS comuns aos dois lados da cortina. Não há nada de especial nessas regras, mas convém ressaltar o uso da propriedade CSS3 box-sizing.

No Box Model CSS às dimensões finais do box são o resultado da soma da largura e altura (width e height) declaradas nas CSS com a espessura de border e padding declarados.

Assim, no nosso exemplo cada folha da cortina teria uma largura igual a 50% + 1px (borda lateral da folha) e uma altura igual a 100% + 10px (borda inferior tracejada da folha). Nessas condições duas consequências indesejáveis seriam imediatas: as folhas somariam uma largura maior do que 100% fazendo a folha direita “cair” (elas são flutuadas em um container (.palco) com 100% de largura) e, como a altura total seria maior do que 100%, a borda inferior tracejada iria desaparecer pois a barra de rolagem vertical foi escondida com a declaração overflow: hidden; no elemento body.

Aqui entra em cena a propriedade box-sizing, cujo valor border-box que inclui a espessura de border e/ou padding na largura total dos boxes, eliminando as duas consequências indesejáveis citadas anteriormente.

Finalmente, para simular as dobras da cortina usamos a propriedade repeating-linear-gradient para criar a imagem de fundo de cada folha da cortina. A declaração da cor vermelha para fundo serve como fallback para navegadores que não suportam gradientes repetidos. Aqui convém ressaltar o uso de porcentagem para definir as repetições do gradiente com a finalidade de redimensionar a largura das dobras da cortina de acordo com a largura da janela do navegador.

***

Oferta exclusiva para os leitores iMasters deste artigo: todos os livros do Maujor com 25% de desconto no site da Novatec Editora! Insira o código promocional maujor25 no carrinho de compras para gerar o desconto. (Válido até 24/01/2013)