Posts Tagged ‘design’

Bordas arredondadas no CSS com uma forcinha do PHP

29 \29UTC junho, 2008

Bordas arredondadas parecem nunca sair de moda. Para a infelicidade dos webdesigners, adicionar mais de uma imagem de fundo a um elemento e a propriedade “border-radius” são exclusividades da versão 3 do CSS, que ainda não é suportada pelo navegador da Microsoft e por isso seu uso está fora de cogitação.

Mas nem tudo está perdido: uma ótima técnica que utiliza CSS2, descrita no artigo “Even More Rounded Corners”, permite mostrar bordas arredondadas utilizando apenas uma imagem PNG com a caixa inteira e uma porção de declarações “background-position” para fatiar virtualmente a imagem. Como todas as soluções compatíveis com o IE, ela necessita de marcação extra no HTML para funcionar. Na verdade, ela é bem compacta, vejam:

<div class="dialog">
<div class="content">
<div class="t"></div>
<!-- Seu contéudo vai aqui --></div>
<div class="b">
<div></div>
</div>
</div>

Mesmo compacta ela ainda causa, em menor intensidade, os mesmos já conhecidos problemas das marcações extras:

  • Dificuldade de manutenção: é necessário reproduzir a estrutura cada vez que quisermos uma caixa arredondada.
  • Perda de legibilidade: seu conteúdo ficará escondido num mar de DIVs inúteis.
  • Quebra de encapsulamento: tags com propósito unicamente visual (DIVs vazias!) tornam o código menos semântico e intuitivo.

Não sendo possível diminuir mais a quantidade de porcaria marcação inútil servida para o usuário, podemos ao menos reduzir algumas linhas do nosso código fonte no servidor, utilizando o PHP.

A solução aqui apresentada permitirá escrever no fonte:

<div class="dialog">
<!-- Seu conteúdo vai aqui --></div>

E ter como resultado o código “sujo” da técnica do “Even More Rounded Corners” na saída. O truque é fazer com que o PHP injete as divs necessárias e sirva para o usuário a marcação extra sem sujar o fonte, melhorando legibilidade, facilitando a manutenção e evitando em certo nível a quebra de encapsulamento. Para executar a mágica vamos usar o controle de buffer de saída do PHP e a extensão DOM, para manipular o HTML.

Primeiro, vamos precisar adicionar o seguinte código no início da página, fazendo com que ele execute antes do script emitir qualquer saída:

<?
// Captura a saída em um buffer.
ob_start();
?>

Isso garantirá que toda a saída do PHP seja guardada em um buffer, ao invés de ser enviada diretamente ao user agent.

O próximo e último passo é pegar toda a saída e injetar a marcação extra. Isso deve ser feito, é claro, no fim do script, depois de qualquer saída ter sido gerada e, conseqüentemente, guardada no buffer:

<?
// Lê o buffer de saída para uma variável string.
$saida = ob_get_contents();

ob_end_clean();

// Defina aqui a classe a ser considerada
// para caixas arredondadas.
$classe = "dialog";

// Carrega o documento na classe DOM.
$dom = new DomDocument("1.0");

// Detecta a codificação da página.
if (
  mb_detect_encoding(
  $saida . 'a' , 'UTF-8, ISO-8859-1' )
  ==
  "UTF-8"
  )
{
  $saida = utf8_decode($saida);
}
$dom->loadHTML($saida);

// Seleciona todas as DIVs
$divs = $dom->getElementsByTagName("div");

foreach ($divs as $div) {

  // Filtra as DIVs da classe selecionada.
  if (strstr($div->getAttribute("class"), $classe)) {

    // Cria os nós adicionais
    $content_div = $dom->createElement("div");
    $content_div->setAttribute("class", "content");

    $t_div = $dom->createElement("div");
    $t_div->setAttribute("class", "t");

    $b_div = $dom->createElement("div");
    $b_div->setAttribute("class", "b");

    $extra_div = $dom->createElement("div");

    // Cria a árvore correta
    $b_div->appendChild($extra_div);
    $content_div->appendChild($t_div);

    // Importa o conteúdo do div a ser arredondado
    // para dentro de 'content'.
    while ($div->hasChildNodes()) {
      $content_div->appendChild(
      $div->removeChild($div->firstChild)
      );
    }

    // Adiciona tudo de volta à div.
    $div->appendChild($content_div);
    $div->appendChild($b_div);
  }
}

$resultado = $dom->saveHTML();

echo $resultado;

?>

É claro que você não irá copiar e colar esse texto em todas as suas páginas. Você pode usar dois includes (um no começo do documento e outro ao final), e ainda, se você usa algum sistema de templates, fazer esses includes apenas no arquivo do template.

Podemos adaptar essa técnica para várias outras situações onde necessitamos de marcação extra. Podemos ainda adaptá-la facilmente para rodar no lado do cliente, uma vez que as funções DOM do PHP e do javascript são praticamente idênticas. O único porém deste último método é que não podemos garantir que o user agent suporte e esteja com o javascript habilitado e é então sujeitos a falhas, motivo pelo qual escolhi o método server-side.

Agora ninguém mais tem desculpa para fazer cara feia quando tiver que implementar aquele design todo arredondado!