Semântica e as classes

Continuando uma discussão bem bacana que saiu no grupo FrontendBrasil, no Facebook, fiquei com uma vontade enorme de expôr minha opinião mais elaborada do que nos comentários. O Suissa abriu a thread e ela já tem mais de 200 comentários (até hoje 25/10/14) e por isso muita coisa boa pode ter se perdido ao tentar ler por ali (ou ruim, depende do ponto de vista =D).

Primeiramente, o Suissa postou um artigo bacana sobre OOCSS revisado por ele, segue o link pra você checar e se aprofundar mais ainda sobre o assunto.

Agora, vamos entrar mais a fundo?

Semântica no front

O Diego Eis do tableless tem uma excelente palestra sobre semântica, simples e objetiva, e que considero importante pra definirmos alguns pontos sobre o assunto.

O significado de semântica no HTML é simplesmente traduzir e organizar informação em forma de código. No nosso caso, para uma linguagem de marcação.

Tendo esse conceito na cabeça, podemos definir que:

  • usar tags que não organizam informação é ruim (<div> pra tudo, por exemplo.).
  • o CSS não deve mandar na semântica;

Outras coisas que podemos e DEVEMOS usar como guia:

  • microdata deve ser aplicado para dar sentido ao seu conteúdo (doc do W3C);
  • WAI-ARIA precisa ser aplicado pra garantir acesso a usuários que tem necessidades especiais (doc sobre WAI-ARIA);

Isso tudo quer dizer então que, a forma que você estrura seu HTML infulencia e MUITO como essa informação é traduzida pra determinadas pessoas.

Mas e onde entram os atributos?

Um atributo de um elemento tem como principal objetivo adicionar propriedades ou definir características a ela.

Um <form> que tem um atributo method definido como POST significa que o verbo HTTP a ser usado no submit do mesmo é o POST. Assim, um <form method="POST"> foi alterado para funcionar de outra forma, além do padrão.

TIP: Para formulários que não possuem o atributo method, o verbo default é o GET.

Esse mesmo <form> com um atributo url definido como /meusite significa que a url em que as informações serão enviadas (ou solicitadas) é /meusite. Novamente, o objetivo do <form> foi alterado aqui.

Percebem que, com alguns atributos eu consigo mudar a interpretação e o sentido de um objeto de marcação?

Se definimos que, o HTML serve para traduzir e organizar informações, nesse caso o nosso formulário agora tem uma outra tradução e sentido aqui.

Com isso, na minha opinião, a semântica desse formulário foi alterada!

Não se trata de deixar o <form> mais bonito, clean ou com menos atributos. Definimos a função e características dele dentro do contexto da página toda.

E o lance das classes?

O ponto polêmico que tem se disseminado em várias discussões por aí é que, o atributo class de um objeto (ou tag), se for populado com muita informação influenciará numa má semântica. E é aí que eu finco minha estaca contra essa posição.

Citando aqui um doc da W3C de 2001 (sim, antigaço!) encontrei um texto que me deixa mais confortável pra desmistificar que class deve ser populado com pouca informação:

(EN) The class attribute assigns one or more class names to an element. The element may be said to belong to these classes. A class name may be shared by several element instances.

O atributo class atribui um ou mais nomes de classe a um elemento. O elemento pode-se dizer que pertence a essas classes. Um nome de classe pode ser compartilhado por várias instâncias do elemento.

http://www.w3.org/TR/2001/PR-SVG-20010719/styling.html#ClassAttribute

Veja aqui que, o elemento que possuir determinadas classes praticamente pertence a elas. O que entendo é que, uma classe possui instâncias, e essas são os elementos.

Semântica, classes... e aí?

O que temos já a um bom tempo é o uso de frameworks de CSS que nos ajudam a componentizar os elementos, criando padrões e forçando a reutilização de código CSS. E isso é muito bom!

O Bootstrap, Foundation, Pure, entre outros fazem exatamente essa função e até outras como componentizar "widgets" e outros comportamentos de javascript.

Acontece que, pra componentizar um elemento, significa que precisamos associá-lo a determinadas classes, roubando um pouco do conceito de Orientação a Objetos.

Partindo desse pressuposto, temos alguns cenários que a princípio parecem esquisitos, como:

# exemplos usando Bootstrap

1. <span class="glyphicon glyphicon-asterisk"></span>

2. <div class="container"></div>

3. <div class="modal"></div>

4. <button type="submit" class="btn btn-default">Submit</button>

Todos esses elementos são semânticos? Pergunta bem subjetiva...

Nos casos 1, 2 e 3 percebemos que, elementos sem nenhuma responsabilidade de traduzir informação foram usados. <span> e <div> realmente tem funções semânticas muito pobres!.

span

No caso 1, o <span> só foi usado pra representar um ícone. Mas qual é a função original de um <span>, segundo a W3C:

(EN) The span element doesn't mean anything on its own, but can be useful when used together with the global attributes, e.g. class, lang, or dir.

O elemento span não significa nada por si só, mas pode ser útil quando usado em conjunto com atributos globais, por exemplo, class, lang, ou dir.

http://www.w3.org/TR/2011/WD-html5-20110525/text-level-semantics.html#the-span-element

O <span> então, não tem um sentido semântico sem os atributos. Portanto, usar uma class "glyphicon" ou "glyphicon-asterisk" define que aquele <span> pertence a uma classe de elementos que possuem certas características de layout ou até comportamento. Melhorou, mas ainda só um pouquinho.

div

No caso 2 e 3, temos um problema grande de interpretação, que é adicionar uma <div> apenas para marcar um conteúdo. Não deixa de ser errado, pois a <div> tem quase o mesmo sentido do <span>. E o problema é que ele não tem sentido nenhum para nossas informações. A galera da W3C até deixa uma nota no doc do HTML5:

(EN) Authors are strongly encouraged to view the div element as an element of last resort, for when no other element is suitable.

Os autores são fortemente encorajados a ver o elemento div como um elemento de último recurso, quando nenhum outro elemento é adequado.

http://www.w3.org/TR/2011/WD-html5-20110525/grouping-content.html#the-div-element

Então, quando for possível, não deveríamos usar <div>. Na web temos vários exemplos com as novas tags do HTML5 que encorajam e explicam como os desenvolvedores devem organizar melhor a informação, usando <section>, <article>, <aside>, etc. (http://www.w3.org/TR/2011/WD-html5-20110525/sections.html).

button

No caso 4, o <button> já tem um sentido muito mais definido do que os 3 primeiros exemplos. Ele é um botão, simples assim. Já os atributos podem modifica-lo pra que o contexto dele seja influenciado dependendo de como você quer.

Ok, ok... e a class e a semântica cara?

Beleza. Se uma classe determina que um elemento pertence a ela, podemos dizer que a semântica dele pode ser alterada usando classes!

"Como assim, uma classe tem valor semântico?". Sim! Então usar col-xs-4 é semântico? Não é por aí...

O problema das classes é que muitos definem seus nomes de forma abreviada ou com um sentido estranho. E em alguns casos, usamos por exemplo um text-red pra definir que aquele texto deve ser vermelho. Digo isso porque às vezes me pego fazendo isso também... mea culpa.

"Então o framework que eu uso não é de todo semântico por causa das classes?". Se entendemos que, pra ser semântico, outros usuários, máquinas, crawlers e etc. precisam entender a informação, a class precisa conter um nome que faz sentido para o conteúdo. E vamos combinar que, col-xs-4 não é tão "entendível" pra qualquer um...

Melhor então construir do zero, né?

Lógico que não! Podemos converter esses errinhos semânticos usando algumas "táticas" bem simples.

# O que era:

    <div class="container"><div>

# Pode virar:

    <section class="container"><section>

# Ou:

    <div class="container" role="region"><div>

Melhorou agora né? Temos um elemento que pertence a uma classe e pode ter regras de layout ou comportamento, com valor semântico, legível e classificado!

Outro exemplo:

# O que era:

    <div class="modal"><div>

# Pode ser:

    <section class="modal" role="dialog"></section>

Nesse caso o role ajuda a entender que um elemento da classe "modal" tem o papel de ser um "dialog", uma janela. Semântico agora hein?

E as grids?

Polêmico! Nesse caso, acho que, quanto mais descrito for o nome da classe, mais identificável fica o nosso conteúdo. Independente de nosso markup ficar mais "feio" com algumas classes a mais.

Volto aqui a usar o exemplo do sistema de grid do Bootstrap:

<div class="row">

    <div class="col-xs-4">

    </div>

    <div class="col-xs-8">

    </div>

</div>

Nesse exemplo, o único ponto que consigo enxergar de semântico é a div com a classe "row", que já falamos que ela é a pior forma de classificar coisas.

E mesmo com a classe é insuficiente pra entender que ali existe uma linha que possui várias colunas de conteúdo. Nem vamos falar nesse esquema de col-(xs|sm|md|lg), que admito ser bem ilegível - é prático só depois que você se acostuma.

Mas como falamos no começo, a semântica não pode ser exclusiva. Você não pode criar um sistema de classificação de conteúdo só seu e não compartilhar isso com as pessoas ou máquinas que interpretam o que você escreve.

Como podemos melhorar isso?

<div class="row">

    <section class="col-xs-4 col-md-3" role="gridcell">

    </section>

    <section class="col-xs-8 col-md-9" role="gridcell">

    </section>

</div>

Dessa forma "falamos" a quem acessar nossa informação que, temos uma linha ("row") que possui duas células-grid. Acredito que assim acabamos com o possível problema semântico de usar essas nomenclaturas estranhas para classes.

Podemos fazer do seguinte modo também:

<div class="row" itemscope itemtype="http://schema.org/ItemList">

    <section class="col-xs-4 col-md-3" role="gridcell" itemprop="itemListElement">

    </section>

    <section class="col-xs-8 col-md-9" role="gridcell" itemprop="itemListElement">

    </section>

</div>

Usei o "ItemList", mas você pode dar outros significados para uma grid, por exemplo, um "Movie", um "Table"... Qualquer coisa que você queira atribuir a esse markup, como:

<div class="row" itemscope itemtype="http://schema.org/Table">

    <section class="col-xs-4 col-md-3" role="gridcell" itemprop="dateCreated">

    </section>

    <section class="col-xs-8 col-md-9" role="gridcell" itemprop="headline">

    </section>

</div>

Agora temos uma tabela que tem elementos como "dateCreated" e "headline". Esses caras ajudam a dar um outro sentido pra sua informação!

col-xs-*

Se mesmo assim você estiver insatisfeito, a maioria dos frameworks te dá a liberdade de modificar a semânticas dos grids de forma bem fácil. O Bootstrap (de novo ele) tem sua versão em LESS e até uma em Sass que permitem usar os mixins que criam as grids e customizá-los da forma que você achar melhor.

Desse modo você pode criar um column-phone-4 por exemplo. Melhora o entendimento, mesmo escrevendo coisa a mais:

<div class="row" itemscope itemtype="http://schema.org/Table">

    <section class="column-phone-4 col-tablet-3" role="gridcell" itemprop="dateCreated">

    </section>

    <section class="col-phone-8 col-tablet-9" role="gridcell" itemprop="headline">

    </section>

</div>

Vantagens e desvantagens

Note que o foco aqui foi semântica, mas e sobre outras questões como DRY, reusabilidade, performance, manutenibilidade, etc.?

Levando em conta tudo o que falamos, ainda acho que o uso de classes contribui sim pra uma melhor reusabilidade. Digo isso porque, a pergunta que sempre deve ser feita nesse caso, é se esse elemento não pertence a nenhum outro tipo já existente no seu projeto. Sempre pergunte isso! Repete aí "ESSE TIPO DE ELEMENTO JÁ NÃO EXISTE?". Aeee!

Assim você deixa seu código mais DRY, reusa propriedades e aumenta a performance do seu CSS, já que, escrevendo menos código, menos informação precisa ser carregada pelo usuário.

A manutenibilidade é garantida nesse caso também, pois criando classes, a possibilidade de extender responsabilidade de layout é bem maior do que especificar propriedades a um elemento sozinho.

Abusando dos pré-processadores

"Mas se eu usar extend também consigo resolver esses problemas todos". É verdade! Mas não consegue resolver o problema de especificidade de código. Desse modo você acaba criando muitos elementos que extendem determinadas propriedades, que poderiam ser uma única classe no seu CSS.

Uso bastante o @extend no Sass, mas não pra essa finalidade de inserir em todo canto uma "classe pai". Pra isso eu adiciono classes no meu markup que façam sentido para o contexto da informação. De novo, semântica baby =D.

Cuidado

Só tome cuidado com os exageros. Em alguns casos, as classes fazem mais mal do que bem:

<div class="left red bordered bordered-green bordered-no-top......"></div>

Se isso começar a crescer, você precisa começar a entender o porquê desse elemento precisar de tanta classe assim. Lembre do mantra: "ESSE TIPO DE ELEMENTO JÁ NÃO EXISTE?".

Será que não vale a pena criar um novo tipo de classe abrangendo essas propriedades? Avalie com cuidado pra não exagerar!

Considerações finais

Use classes com nomes legíveis, tags que façam sentido, microdata, WAI-ARIA e tudo que facilite o entendimento da informação que você quer passar.

Não fique preso em coisas como beleza do markup ou tique nervoso por excesso de atributos. Foque em apresentar o conteúdo da forma mais completa e classificada possível!

Afinal, a informação precisa ser entendível, decifrada por todo e qualquer tipo de pessoa ou dispositivo, e não pra sua vaidade própria!

Comenta ae!

Conta mais aí nos comentários sobre o que acha disso tudo e que comecem as boas discussões!

comments powered by Disqus