Capítulo 4
Entender a sintaxe e as propriedades do CSS é vital, porém mais importante do que isso é aprender alguns truques e técnicas para resolver problemas do dia a dia. Só saber a linguagem não é o suficiente, é preciso saber como usá-la e quais são as suas opções quando precisar colocar a mão na massa.
Todos os navegadores, das primeiras versões do Internet Explorer aos navegadores de celulares e tablets, possuem estilos padrões que são aplicados em todas as páginas, como o negrito da tag strong, a borda do legend e os tamanhos de fonte diferentes do h1 ao h6. E é claro que existem diferenças entre os padrões de um navegador para outro. Algumas dessas diferenças, por menores que possam ser, costumam afetar o nosso trabalho, impactando no resultado final das nossas páginas quando visualizadas em diferentes navegadores e soluções específicas para estes cenários precisam ser utilizadas.
Para entender melhor esta situação, podemos testar um pouco de HTML, sem estilos, e ver como que ele será exibido no Google Chrome e no Firefox, por exemplo.
Conseguimos notar leves diferenças, que podem impactar o nosso trabalho final. As bordas do fieldset, a ausência do sublinhado no elemento abbr no Chrome e as diferenças dos campos de busca e de texto.
Como qualquer problema recorrente no mundo de desenvolvimento, soluções já foram criadas para não nos preocuparmos com coisas assim e focarmos no trabalho de verdade. Os arquivos de reset, como são chamados, possuem uma gama de regras para alinhar os navegadores em um mesmo patamar de estilo, seja corrigindo problemas ou resolvendo inconsistências.
Talvez o mais famoso dos resets seja o escrito por Eric Meyer, que criou a versão 1.0 em 2008 — bastante tempo, não? — sua última atualização foi feita em 2011, e você pode encontrá-la no próprio blog do seu criador, http://meyerweb.com/eric/tools/css/reset/.
Os desenvolvedores do Yahoo! também criaram um reset sólido, parte do Yahoo! User Interface Library, disponível no site http://yuilibrary.com/. Um ponto negativo do reset do Yahoo! é que ele remove alguns padrões que eu considero importante em alguns elementos, como o negrito da tag strong e a marcação lateral de itens em uma lista.
Normalize.css
O Normalize.css (http://necolas.github.com/normalize.css/), é o reset que estamos utilizando neste livro e toma uma abordagem diferente a este problema. No lugar de sobrescrever diversas propriedades para definir um novo padrão de estilo para os navegadores, ele apenas adequa os pontos diferentes, preservando diversos estilos aplicados pelos navegadores, além de aproveitar para definir algumas melhorias sutis, removendo o outline de links e melhorando a formatação de elementos pre, por exemplo.
O código fonte do Normalize é muito bem escrito e documentado, o que lhe permite remover partes dele que não te interesse ou entender melhor o que ele faz por debaixo dos panos. Confira o exemplo de código a seguir:
Cada propriedade é devidamente documentada, e sabemos quais versões dos navegadores precisa das correções. Caso você não queria se preocupar com versões do Internet Explorer abaixo da 8, por exemplo, você pode remover do código fonte do Normalize as regras específicas destas versões.
Independente de qual reset você for usar, o mais importante é estar usando um, e faça disso parte do seu processo de desenvolvimento ao participar de novos projetos.
Isto não tira a responsabilidade de testar manualmente as páginas em diversos navegadores, mas impede que alguns problemas relacionados a posicionamento, tamanhos e fontes apareçam do nada e você tenha que dedicar tempo a esses problemas ao invés de se dedicar ao que precisa ser criado.
Não importa quais cores, imagens de fundo ou posição você adicionar em um elemento, ele sempre será tratado como uma caixa. Isto pode não ser perceptível a primeira vista, mas basta começar a usar um inspetor de elementos como o Firebug ou o console do WebKit e você irá se acostumar com esta abordagem. O Box model é como as propriedades de CSS compõem as dimensões, onde além do width e do height, as propriedades border e padding também influenciam no resultado final, mas de uma forma um tanto quanto confusa. Considere o código a seguir.
Esta classe button, ao ser aplicada em um elemento qualquer, irá ocupar 122px de largura e 38px de altura na sua página. Isto acontece por que os valores de padding e border são somados a largura e altura definidas, fazendo com que as propriedades width e height sejam responsáveis por definir apenas a largura e a altura do seu conteúdo, e não do elemento como um todo. Além da confusão que pode ser gerada ao se calcular os tamanhos de antemão, isso torna bastante complicado o uso de valores com porcentagem nestas propriedades — um elemento com 100% de width e 2px de bordas ficará maior do que os 100% definidos. Complicado, não?
Outro exemplo para ilustrar este problema: ambos elementos possuem o mesmo valor de width, mas o valor do padding do segundo o deixa com 300px de largura.
Esta regra do Box model aplicar estes valores a apenas o conteúdo e não utilizar como limites fixos do elemento como um todo pode complicar diversos casos de diagramação de elementos em páginas complexas, mas é possível alterar este comportamento e não ficar recalculando larguras e alturas baseado em bordas e espaçamentos. A propriedade box-sizing, uma das novidades do CSS 3, permite alterar esta regra de content-box para o valor border-box, que força o navegador a respeitar estes limites e ocupar o espaço interno do elemento com os valores de border e padding, no lugar de expandir o elemento.
Desta forma, as duas definições abaixo irão gerar elementos com a mesma largura.
Existem casos onde as tags que utilizamos para definir o nosso conteúdo não são o suficiente para estruturar os elementos de interface que desejamos. Seja para tratar problemas de float, definir bordas adicionais ou algo similar, muitas vezes acabamos dependendo de elementos vazios para resolver estes problemas. Por exemplo, ao trabalhar com bordas arredondadas sem o uso de CSS 3, já vi (e escrevi), coisas assim, onde o span é utilizado para criar as bordas do lado direito de um botão.
Já foi muito comum utilizar soluções assim para trabalhar com sombras, bordas arredondadas, letras iniciais de títulos e outros detalhes de interface que não conseguimos criar apenas com o mínimo de código HTML. Mas existem alternativas bastante interessantes para isto, utilizamos apenas CSS. São pseudo elementos, que não existem no nosso código HTML, mas podem receber estilos específicos e auxiliar a estruturar elementos mais complexos nas nossas interfaces. Os mais tradicionais deles são os elementos ::before e ::after, que vivem antes e depois do conteúdo de uma tag (e não antes e depois da tag em si), e estão disponíveis para todas as tags que adicionarmos ao body da nossa página.
Vamos criar uma faixa que dá a ilusão de que ela contorna um section que o contém, e os elementos ::before e ::after irão fazer o trabalho pesado para a gente. Começamos com o mínimo de HTML necessário, uma tag section e um título para a faixa.
Vamos adicionar um pouco de CSS para definir a largura do section e a posição do título.
Vamos começar a transformar o nosso h1 na faixa que queremos criar. Além da cor, vamos posicionar as laterais da faixa para fora da seção.
Agora, temos 10px de cada lado da faixa vazando pela seção, só precisamos criar o efeito da faixa contornando o section, utilizando pseudo elementos. Primeiro, vamos criar este efeito para o lado esquerdo da faixa, utilizando o ::before.
Fazemos referência ao before utilizando a mesma sintaxe de pseudo classes que utilizamos para links, com o : separando os elementos.
Utilizando o position junto de coordenadas exatas com as propriedades left e top, conseguimos posicionar o elemento exatamente no canto superior esquerdo da faixa e com uma borda de 5px, desenhamos um quadrado de 10px.
A propriedade content é utilizada para definir o conteúdo do elemento — já que não estamos adicionando o elemento pelo HTML — e neste caso não precisamos de conteúdo algum. Para conseguir o efeito que queremos, precisamos transformar o quadrado que criamos em um triângulo, só precisamos de um ajuste nas cores das bordas.
Trocando algumas das cores para transparent, conseguimos desenhar um triângulo no lugar do quadrado vermelho. Para duplicar este efeito no outro lado da faixa, utilizando o ::after, só precisamos inverter alguns detalhes — o que era feita com a propriedade left será feito com a right, e as posições da lista de cores também precisa ser modificada, desta forma.
Feito! Criamos o efeito da faixa contornando a seção, sem precisar de novos elementos no HTML.
É comum ver por aí o uso dos pseudo elementos before e after em duas formas diferentes: prefixada com dois pontos (:before) ou quatro pontos (::before). Você sabe a diferença entre eles?
Efetivamente, nenhuma. A especificação do CSS 2 criou a versão com dois pontos, mas ela foi mudada no CSS 3 para ser diferente das definições de pseudo seletores. Navegadores modernos possuem suporte aos dois formatos, enquanto algumas versões antigas só entendem o formato de dois pontos do CSS 2.
Outra utilidade dos pseudo elementos é criar formas de botões que antes só era possível com o uso de imagens de fundo. Usando uma lógica similar à utilizada no exemplo da faixa, podemos criar um balão de ajuda com uma indicação sobre o que ele é a respeito. Imagine o seguinte parágrafo, sendo usado em um formulário de cadastro de um site de um concurso qualquer:
Podemos adicionar um pouco de estilo e transformar este parágrafo em uma caixa de ajuda.
Considerando que este elemento está ao lado de um campo de e-mail, podemos simular uma seta na lateral da caixa de ajuda apontando para o campo do formulário, demonstrando a relação entre a mensagem e o campo que o usuário irá preencher. Utilizar o ::before para criar esta seta é uma ótima opção.
Utilizamos a mesma lógica das bordas da faixa que criamos anteriormente para transformar este elemento em um triângulo, e definimos a posição exata dele com a combinação da propriedade position e das coordenadas com top e left. Mas parte do truque é a propriedade top com 50% e a margin-top negativa, o que força o elemento a ficar sempre centralizado, independente da altura do parágrafo.
Além de serem bastante úteis para desenhar novos elementos na página, estes pseudo elementos também podem gerar conteúdo para complementar seus elementos de referência. A propriedade content aceita pedaços de texto para preencher o seu conteúdo — mas você não pode adicionar código HTML, infelizmente.
Talvez o exemplo mais clássico dessa funcionalidade é o de exibir o endereço de links da página logo após o seu texto — uma ótima pedida para estilos de impressão, que veremos logo mais neste capítulo. Mas também podemos adicionar ícones e outros tipos de elementos decorativos para complementar o nosso conteúdo. Exemplo, em um texto informativo não tão relacionado, conseguimos adicionar a indicação de uma mão apontando para o texto, assim:
Para posicionar uma indicação próxima ao texto, basta o uso do ::before junto de um símbolo Unicode que representa uma mão apontando o dedo.
Pronto — não precisamos de uma imagem de um ícone específico para isso.
Outro caso de uso para gerar conteúdo com pseudo elementos é ao adicionar estilo a elementos de citação, como o blockquote. É bastante simples adicionar aspas em torno do texto para indicar que aquele conteúdo se trata de uma citação. Começando com o mínimo necessário de HTML:
E um pouco de CSS para formatar a citação:
Podemos adicionar aspas ao redor do texto, com uma fonte maior e uma cor diferente, apenas adicionando o conteúdo necessário no ::before e ::after e ajustando o seu estilo como necessário.
Como o ::before e o ::after herdam as propriedades do seu elemento, precisamos sobrescrever a cor do texto e definir um tamanho de fonte (três vezes) maior.
Como você pode ter notado em alguns dos nossos exemplos, as propriedades position, top e left são bastante importantes para garantir que nossos pseudo elementos estejam em seus lugares exatos. Não deixe de conferir a seção 6.4, onde iremos conferir em detalhes o uso destas propriedades.
Escrever CSS pode ser fácil, mas escrever CSS bem escrito é uma habilidade relativamente rara e preciosa. Conforme os seus projetos vão ganhando novas funcionalidades e sofrendo mudanças visuais, você pode se encontrar em situações onde alterar os estilos de um elemento ou adicionar uma variação de algo existente pode ser uma tarefa herculana, e a duplicação de código só traz mais complicações e problemas para a sua equipe e o seu projeto. Por isso, é importante refletir sobre o código CSS escrito e tratar a sua manutenção com a mesma atenção que se cuida do código da sua aplicação, independente da linguagem que você utilize.
Escolha bem seus seletores
Um dos vilões clássicos de um CSS mal cuidado é a complexidade de seletores usados. Além da degradação da performance das suas páginas, compreender o escopo de um seletor para alterar alguma propriedade pode ser complicado.
Para entender o impacto de performance é necessário entender como os navegadores processam os seletores que escrevemos. Considere o seguinte seletor: ul#nav li a.
O navegador começará a ler o seletor de trás para frente — ao contrário do que nós estamos acostumados a ler, o que surpreende diversos desenvolvedores — e irá procurar na página todos os elementos da tag a. Após isso, ele irá filtrar esta lista por todos que estejam contidos em um elemento li, e então por todos que também estejam dentro de um elemento com id nav. E por fim, todos em que o elemento com o id nav seja da tag ul.
Considerando que o HTML para uma estrutura dessas seria uma lista não ordenada apenas com links, algo como #nav a seria uma solução mais simples para o navegador processar, e com o mesmo efeito. Ou até mesmo utilizando uma classe nav-link, por exemplo, diretamente nos elementos a dentro da lista com o id nav.
Outro ponto que gera muita discussão e confusão entre desenvolvedores: utilizar ids ou classes? Enquanto ids podem ser mais rápidos para o navegador procurar os elementos necessários na árvore do DOM, a diferença de performance é ínfima, então a discussão acaba mais no assunto de preferência pessoal. Classes são ótimas para compor diversos aspectos compartilhados entre vários elementos, e ids ajudam a indicar que o seletor é específico para um elemento único da página.
Uma regra pessoal que eu tento seguir é evitar seletores com mais de 3 partes, como header .nav a. Caso você se encontre escrevendo seletores maiores que algo assim, pare e reveja a sua estrutura para que não seja necessário escrever seletores tão grandes — seja utilizando mais classes ou reduzindo a especificidade dos seus seletores.
Compondo padrões visuais através de classes
Nicole Sullivan popularizou uma abordagem na escrita de CSS e composição de estilos, similar a Orientação a Objetos, que é utilizada em linguagens de programação. O OOCSS — Object Oriented CSS — propõe a separação da estrutura dos estilos e os containers de seu conteúdo.
O objetivo é escrever um código mais fragmentado e reutilizável, onde diversas classes diferentes são utilizadas para compor o comportamento final de um elemento, independente da tag que ele possua ou o contexto que ele se encontre — dentro de uma lista, um formulário ou o cabeçalho da página.
Tome como exemplo os 2 botões a seguir.
Podemos separar os aspectos destes elementos em 4 classes diferentes: uma para definir os estilos básicos de um botão, uma para as cores do botão principal, e outras duas para controlar os tamanhos de cada um, assim:
Desta forma, botões em outras páginas e que possuam detalhes diferentes (como uma cor de fundo diferente, ou um ícone posicionado ao lado do texto) podem compartilhar os estilos básicos de um botão e aplicar os seus pontos específicos com outras classes, como danger-button ou icon-button. Esta abordagem pode ser estendida para menus de navegação ou conteúdos relacionados, ou uma relação de posts — o famoso media object dos exemplos tradicionais de OOCSS.
Os navegadores nos permitem adicionar estilos específicos para quando uma página for impressa pelo usuário. Isto pode ser feito de duas maneiras: Com o atributo media na tag link ou criando um bloco de CSS dentro da diretiva @media print, conforme os exemplos a seguir.
A primeira forma é a mais adequada, já que evitamos uma nova requisição ao arquivo de impressão. E como os estilos de impressão costumam ser pequenos, não existem problemas em adicionar este CSS ao final do estilo padrão da sua página.
Pode-se considerar que a impressão de páginas é algo do passado, mas dependendo do tipo de conteúdo que você trabalha, e o seu público, isto pode ser bastante importante para o seu projeto.
Por exemplo, ao utilizar o Airbnb (http://airbnb.com) para alugar um apartamento para uma viagem aos Estados Unidos, é interessante imprimir o itinerário da viagem, que possui endereços, datas e telefones úteis caso você tenha algum problema ao pousar no seu destino, onde você provavelmente não terá uma conexão de internet disponível logo ao chegar. Ou ao criar um trajeto pela cidade no Google Maps, você pode imprimir o mapa com o seu roteiro para ter em mãos ao dirigir.
Além disso a impressão das páginas não fica resumida a ter o conteúdo em uma folha de papel, já que hoje em dia é bastante simples de se exportar uma página da web para um arquivo .pdf utilizando o processo de impressão dos navegadores. Você consegue compartilhar páginas e e-mails ou arquivar páginas de recibos de compras ou pagamentos de serviços pela internet.
Independente do tipo de conteúdo que você estiver trabalhando, existem práticas recomendadas para tratar os estilos de impressão, visando a legibilidade do seu conteúdo e tirando elementos desnecessários da frente de coisas mais importantes. Vamos repassar alguns deles.
Não conte com cores
Não podemos depender da qualidade e da gama de cores disponíveis ao imprimir a página, pois não temos controle ou informações sobre a qualidade do hardware ou da disponibilidade de tinta, então o recomendado é se manter no branco e preto de praxe. Então podemos remover todo tipo de cor ou imagem de fundo, e forçar a cor do nosso texto, assim:
O uso do !important é para garantir que esta regra sobrescreva qualquer outro seletor mais específico do seu CSS padrão, para garantir que tudo se mantenha na cor preta. Além disso, é recomendado remover qualquer outra propriedade de estilo visual, como box-shadow e text-shadow, além de revisar a cor das bordas utilizadas.
Ao remover a propriedade background completamente, também estamos removendo imagens de fundo. Caso alguma destas imagens devesse estar presente na sua versão de impressão, considere movê-la para uma tag img. E o contrário também — navegações criadas com imagens deveriam ser trocadas por texto simples ao ser impresso.
Links devem ser links
Com a ausência de cores, todos os seus links azuis, verdes ou vermelhos terão a mesma cor preta do seu conteúdo. Uma forma de diferenciar os links do texto comum é sublinhando-os, caso você tenha retirado isto do estilo dos seus links.
Outra técnica recomendada para tratar links em casos de impressão é exibir o caminho que eles possuem logo após o seu texto. Isto é possível utilizando o pseudo elemento ::after dos links, junto da função attr(), que permite ler os atributos de um elemento através de CSS.
Desta forma, todos os links com um href presente terão o seu caminho exibido entre parênteses ao seu lado. Links que não possuem uma url a seguir, como links que utilizam funções de JavaScript não devem receber este efeito, então precisamos remover o pseudo elemento nestes casos, utilizando um seletor mais específico que o anterior:
Controlando quebras de páginas
Enquanto no navegador o nosso conteúdo existe em apenas uma página, na impressão existe a necessidade de se quebrar o conteúdo em páginas de acordo com a configuração do usuário. Por padrão isto será feito de acordo com o tamanho da sua página, mas é possível tomar controle sobre isto e definir regras específicas para informar em qual parte do seu conteúdo a quebra de página será feita. Atualmente, existem 3 propriedades disponíveis na maioria dos navegadores para isso: page-break-before, page-break-inside e page-break-after.
O page-break-before e page-break-after definem se a quebra de página deve ocorrer antes ou depois do elemento. A propriedade aceita os valores always, utilizado para forçar a quebra, ou avoid, indicando para o navegador que a quebra deve ser evitada. Com eles é possível, por exemplo, ao imprimir uma relação de posts de um blog, deve existir uma quebra de página entre um post e outro.
Ou caso você precise de um controle mais refinado das quebras, você pode definir um elemento vazio para posicionar as quebras em pontos específicos do seu conteúdo.
E então adicionar uma tag div, por exemplo, com a classe .page-break onde for necessário forçar a quebra de página.
Já com o page-break-inside, que aceita apenas as opções auto e avoid, podemos definir que o conteúdo de um parágrafo não deve ser quebrado entre duas páginas.
Este tipo de controle é interessante para blocos de conteúdo extensos, como manuais, documentações ou mesmo e-books criados em HTML. Além destas 3 propriedades existem outras duas, utilizadas para definir os limites de linhas que deve ficar em uma página ou em outra: orphans e widows. Mas infelizmente estas propriedades não possuem um suporte extenso pelos navegadores.
Impressão de tabelas
Vamos praticar um pouco e melhorar uma tabela de um relatório financeiro com débitos e lucros obtidos. Além dos valores, a tabela possui alguns links para navegar entre os dados e tomar outras ações no sistema. O HTML é bem simples, tendo apenas uma tabela e algumas linhas.
E um pouco de CSS para melhorar o estilo da tabela, definindo sua largura, cores para as bordas das células, alinhamentos e também a definição de links:
Além de definir uma largura para a tabela e definir algumas regras de alinhamento, registros de lucro ficarão com a cor verde e gastos serão exibidos em vermelho. Ao imprimir esta página em preto e branco não possuímos nenhuma distinção visual disso e os links não estarão disponíveis no papel. Vamos escrever algumas regras de CSS para impressão e ajustar isto.
Primeiro, vamos garantir que todo o conteúdo esteja na cor preta, e que a tabela ocupe o máximo de espaço possível.
Também podemos trabalhar um pouco nos links existentes na página. Os da primeira coluna podem ser expandidos utilizando a técnica do pseudo elemento. Já a coluna com os links de edição é dispensável para a nossa visão de impressão, por ser um elemento de navegação sem nenhum conteúdo relevante para este cenário, podemos então esconder esta coluna inteira.
Por fim, temos a coluna de receitas e débitos a tratar. Indo na onda de pseudo elementos, podemos adicionar duas características a cada célula desta coluna. Um sinal de - ou +, dependendo do caso, antes do valor, e os termos Receita e Despesa.
Com o uso do vermelho e do verde removido nos estilos de impressão, estas indicações serão úteis para identificar o tipo de transação de cada linha. O CSS para adicionar este conteúdo é o seguinte:
Assim é possível adequar diversos aspectos do visual das nossas páginas para o modo de impressão, de acordo com as necessidades dos seus usuários e os objetivos do tipo de projeto que você estiver fazendo. Claro que este tipo de tratamento não é necessário em todos os projetos, mas é uma carta valiosa na sua manga.
0 Comentários