CSS: depois de não adicionar conteúdo a certos elementos

100

Estou tendo problemas para entender o comportamento da :afterpropriedade CSS . De acordo com as especificações ( aqui e aqui ):

Como seus nomes indicam, os :beforee :afterpseudo-elementos especificar a localização do conteúdo antes e depois do conteúdo árvore de documentos de um elemento.

Isso não parece colocar restrições sobre quais elementos podem ter uma propriedade :after(ou :before). No entanto, parece que só funcionam com elementos específicos ... <p>obras, <img>não, <input>não, <table>não. Eu poderia testar mais, mas o ponto é válido. Observe que isso parece bastante consistente em todos os navegadores. O que determina se um objeto pode aceitar uma propriedade :beforee :after?

eykanal
fonte

Respostas:

156

imge inputsão ambos elementos substituídos .

Um elemento substituído é qualquer elemento cuja aparência e dimensões sejam definidas por um recurso externo. Exemplos incluem imagens ( <img>tags), plug-ins ( <object>tags), e elementos de formulário ( <button>, <textarea>, <input>, e <select>tags). Todos os outros tipos de elementos podem ser chamados de elementos não substituídos.

:beforee :aftersó funcionam com elementos não substituídos.

Da especificação :

Nota. Esta especificação não define totalmente a interação de :beforee:after com elementos substituídos (como IMG em HTML). Isso será definido com mais detalhes em uma especificação futura.

Com span:before, span:after, o DOM se parece com isto:

<span><before></before>Content of span<after></after></span>

Evidentemente, isso não funcionará <img src="" />.

trinta pontos
fonte
2
"O conteúdo gerado não altera a árvore do documento." Eu ficaria surpreso se você pudesse encontrar algo como " <before></before>" na fonte.
Knu
4
@Knu: Você está certo, expliquei mal. Você nunca vai encontrar <before></before>. Eu deveria ter dito "fingir DOM" ou algo assim. O objetivo era mostrar isso :beforee :afterestão dentro do elemento, não fora dele.
thirtydot
Não, eles não são armazenados no DOM shadow.
ferramenta
3
A especificação citada não diz isso :beforee :afternão funciona para elementos substituídos; apenas diz que não “define totalmente” como e que isso será definido no futuro (o que não aconteceu até agora). O que acontece no DOM é irrelevante aqui. Embora os navegadores não suportem esses pseudo-elementos para alguns elementos, isso não está nas especificações, apenas o que as implementações fazem.
Jukka K. Korpela
Eu costumava considerar lógica a explicação de que ::beforee ::afternão funcionam para elementos void (vazios) que nunca têm conteúdo real, antes / depois do qual eles poderiam ser aplicados. Mas, surpreendentemente, eles funcionam para o hrelement em quase todos os navegadores.
Ilya Streltsyn
9

:beforee :afternão precisam funcionar para elementos substituídos, e as especificações CSS não especificam como funcionariam para eles, e o conceito de elemento substituído é um tanto vago.

A especificação CSS 2.1 sugere claramente que eles podem funcionar para elementos substituídos, apenas dizendo que não "define totalmente" como. Isso está relacionado ao problema de que um elemento substituído deve ter sua própria renderização visual, que não é controlada por CSS, enquanto os pseudoelementos devem adicionar algo ao conteúdo do elemento. A especificação acrescenta que isso será definido “com mais detalhes” em uma especificação futura, mas isso não ocorreu até agora.

Os fornecedores de navegadores decidiram evitar problemas ao não implementar esses pseudo-elementos para alguns elementos.

Não está claro o que significa “elemento substituído”, e o significado parece ter mudado um pouco. Muitas vezes é interpretado como significando o mesmo que um elemento vazio (um elemento com EMPTYconteúdo declarado, ou seja, um elemento que não pode ter nenhum conteúdo), mas o próprio CSS 2.1 mostra uma folha de estilo de amostra com o seletor br:before(embora os navegadores tenham ignorado isso, implementando brseus próprios maneira). Pode-se argumentar que mais e mais elementos foram movidos para o escopo da renderização CSS, pelo menos em parte. Por exemplo, um inputelemento (incluindo sua fonte, cores, etc.) é amplamente controlável com CSS em navegadores modernos.

Os navegadores atuais (Firefox, IE, Chrome) não parecem suportar o :after e :beforepseudo-elementos para fins diferentes elementos vazios hr. Pois hr, o IE e o Chrome colocam o conteúdo gerado dentro de uma caixa delimitada, que é a implementação de hr; o conteúdo torna a caixa mais alta. O Firefox coloca o conteúdo de ambos (!) Pseudo-elementos após a regra horizontal que é sua implementação hr. Esta variação ilustra os tipos de problemas de “interação” mencionados no CSS 2.1.

Freqüentemente, afirma-se que esses pseudo-elementos não podem ser usados ​​para elementos vazios, pois suas definições HTML não permitem nenhum conteúdo. Este é um erro de categoria. As regras de sintaxe de uma linguagem de marcação não restringem o que você pode fazer em CSS

Para concluir, :aftere :beforeatualmente não são utilizáveis ​​para elementos vazios (exceto marginalmente para hr), mas isso é principalmente devido a implementações e pode mudar no futuro.

Jukka K. Korpela
fonte
-1

Os elementos que não possuem tag de fechamento são elementos nulos e não podem exibir o conteúdo dentro deles:

https://www.w3.org/TR/html5/syntax.html#void-elements

Todos os navegadores Blink, Webkit e Quantum permitem que você crie pseudoelementos apenas nas caixas de seleção, mas isso é controverso, pois nenhuma especificação permite esse comportamento.

Aqui está um exemplo: https://codepen.io/equinusocio/pen/BOBaEM/

input[type="checkbox"] {
  appearance: none;
  color: #000;
  width: 42px;
  height: 24px;
  border: 1px solid currentColor;
  border-radius: 100px;
  cursor: pointer;
  transition: all 100ms;
  background-size: 30%;
  outline: none;
  position: relative;
  box-sizing: border-box;
  background-color: #eee;
  transition: background-color 200ms;

  &::before {
    content: '';
    position: absolute;
    left: 2px;
    top: 2px;
    bottom: 2px;
    height: 18px;
    width: 18px;
    border-radius: 50%;
    background-color: currentColor;
    will-change: transform;
    transition: transform 200ms cubic-bezier(.01,.65,.23,1);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  }

  &:checked {
    background-color: aquamarine;

    &::before {
      transform: translateX(100%);
    }
  }
}
Mattia Astorino
fonte
não funcionará em todos os navegadores ... e não há nenhuma especificação que diga que agora podemos ... se você tiver um, compartilhe-o porque não é seguro considerar o pseudo elemento com entrada
Temani Afif
Funciona em todos os navegadores, exceto no IE. Mesmo o flexbox não é suportado pelo IE 9, então onde está o problema. Esta solução funciona em todos os navegadores Blink, Webkit e Quantum e pode ser muito útil para pessoas que trabalham em um ambiente apenas de webkit como Electron.
Mattia Astorino
Como você disse em sua resposta, não há especificação para isso, então um dia pode parar de funcionar. Não é a única coisa que se comporta e funciona sem nenhuma especificação definida, mas nunca devemos confiar nelas e dizer que funcionam. são como tags obsoletas, ainda funcionam, mas devemos parar de usá-las porque um dia não funcionarão. Então, sim, isso pode ser útil para as pessoas e meus comentários também são úteis para alertar as pessoas que elas devem estar cientes de que isso não é oficial.
Temani Afif