O sinal de mais ( +
) é para o próximo irmão.
Existe um equivalente para o irmão anterior?
O sinal de mais ( +
) é para o próximo irmão.
Existe um equivalente para o irmão anterior?
Respostas:
Não, não há seletor "irmão anterior".
Em uma nota relacionada, ~
é para irmão sucessor geral (ou seja, o elemento vem após este, mas não necessariamente imediatamente após) e é um seletor CSS3. +
é para o próximo irmão e é CSS2.1.
Consulte Combinador de irmão adjacente dos seletores de nível 3 e 5,7 Seletores de irmão adjacente da especificação de revisão 2 do Cascading Style Sheets Level 2 Revisão 1 (CSS 2.1) .
Encontrei uma maneira de estilizar todos os irmãos anteriores (opostos a ~
) que podem funcionar dependendo do que você precisa.
Digamos que você tenha uma lista de links e, ao passar o mouse sobre um deles, todos os anteriores devem ficar vermelhos. Você pode fazer assim:
/* default link color is blue */
.parent a {
color: blue;
}
/* prev siblings should be red */
.parent:hover a {
color: red;
}
.parent a:hover,
.parent a:hover ~ a {
color: blue;
}
<div class="parent">
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
</div>
float:right
). Exigiu um colapso de espaço em branco entre unidades / palavras e preenchimento em vez de margens, mas funciona perfeitamente de outra maneira!
O nível 4 dos seletores apresenta:has()
(anteriormente o indicador de assunto !
) que permitirá que você selecione um irmão anterior com:
previous:has(+ next) {}
… Mas, no momento da redação, está a uma certa distância do limite do suporte do navegador.
:has()
pseudo-classe.
order
propriedade dos layouts flex e grid.Vou me concentrar no flexbox nos exemplos abaixo, mas os mesmos conceitos se aplicam ao Grid.
Com o flexbox, um seletor de irmão anterior pode ser simulado.
Em particular, a order
propriedade flex pode mover elementos pela tela.
Aqui está um exemplo:
Você deseja que o elemento A fique vermelho quando o elemento B estiver pairando.
<ul> <li>A</li> <li>B</li> </ul>
PASSOS
Faça ul
um recipiente flexível.
ul { display: flex; }
Inverta a ordem dos irmãos na marcação.
<ul>
<li>B</li>
<li>A</li>
</ul>
Use um seletor de irmão para direcionar o elemento A ( ~
ou +
fará).
li:hover + li { background-color: red; }
Use a order
propriedade flex para restaurar a ordem dos irmãos na exibição visual.
li:last-child { order: -1; }
... e pronto! Nasce um seletor de irmãos anterior (ou pelo menos simulado).
Aqui está o código completo:
ul {
display: flex;
}
li:hover + li {
background-color: red;
}
li:last-child {
order: -1;
}
/* non-essential decorative styles */
li {
height: 200px;
width: 200px;
background-color: aqua;
margin: 5px;
list-style-type: none;
cursor: pointer;
}
<ul>
<li>B</li>
<li>A</li>
</ul>
Na especificação do flexbox:
5.4 Ordem de exibição: a
order
propriedadeOs itens flexíveis são, por padrão, exibidos e dispostos na mesma ordem em que aparecem no documento de origem. A
order
propriedade pode ser usada para alterar essa ordem.A
order
propriedade controla a ordem na qual os itens flexíveis aparecem no contêiner flexível, atribuindo-os a grupos ordinais. É necessário um<integer>
valor único , que especifica a qual grupo ordinal o item flexível pertence.
O order
valor inicial para todos os itens flexíveis é 0.
Veja também order
na especificação CSS Grid Layout .
Exemplos de "seletores de irmãos anteriores" criados com a order
propriedade flex .
.container { display: flex; }
.box5 { order: 1; }
.box5:hover + .box4 { background-color: orangered; font-size: 1.5em; }
.box6 { order: -4; }
.box7 { order: -3; }
.box8 { order: -2; }
.box9 { order: -1; }
.box9:hover ~ :not(.box12):nth-child(-1n+5) { background-color: orangered;
font-size: 1.5em; }
.box12 { order: 2; }
.box12:hover ~ :nth-last-child(-1n+2) { background-color: orangered;
font-size: 1.5em; }
.box21 { order: 1; }
.box21:hover ~ .box { background-color: orangered; font-size: 1.5em; }
/* non-essential decorative styles */
.container {
padding: 5px;
background-color: #888;
}
.box {
height: 50px;
width: 75px;
margin: 5px;
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
cursor: pointer;
}
<p>
Using the flex <code>order</code> property to construct a previous sibling selector
</p>
<div class="container">
<div class="box box1"><span>1</span></div>
<div class="box box2"><span>2</span></div>
<div class="box box3"><span>3</span></div>
<div class="box box5"><span>HOVER ME</span></div>
<div class="box box4"><span>4</span></div>
</div>
<br>
<div class="container">
<div class="box box9"><span>HOVER ME</span></div>
<div class="box box12"><span>HOVER ME</span></div>
<div class="box box6"><span>6</span></div>
<div class="box box7"><span>7</span></div>
<div class="box box8"><span>8</span></div>
<div class="box box10"><span>10</span></div>
<div class="box box11"><span>11</span></div>
</div>
<br>
<div class="container">
<div class="box box21"><span>HOVER ME</span></div>
<div class="box box13"><span>13</span></div>
<div class="box box14"><span>14</span></div>
<div class="box box15"><span>15</span></div>
<div class="box box16"><span>16</span></div>
<div class="box box17"><span>17</span></div>
<div class="box box18"><span>18</span></div>
<div class="box box19"><span>19</span></div>
<div class="box box20"><span>20</span></div>
</div>
O Flexbox está quebrando crenças antigas sobre CSS.
Uma dessas crenças é que um seletor de irmãos anterior não é possível no CSS .
Dizer que essa crença é generalizada seria um eufemismo. Aqui está uma amostra de perguntas relacionadas apenas no Stack Overflow:
Como descrito acima, essa crença não é totalmente verdadeira. Um seletor de irmão anterior pode ser simulado em CSS usando a order
propriedade flex .
O z-index
Mito
Outra crença de longa data tem sido que z-index
funciona apenas em elementos posicionados.
De fato, a versão mais atual da especificação - o Rascunho do Editor W3C - ainda afirma que isso é verdade:
9.9.1 Especificando o nível da pilha: a
z-index
propriedade
z-index
- Valor: auto | | herdar
- Inicial: auto
- Aplica-se a: elementos posicionados
- Herdado: não
- Porcentagens: N / A
- Mídia: visual
- Valor calculado: conforme especificado
(enfase adicionada)
Na realidade, porém, essas informações são obsoletas e imprecisas.
Elementos que são itens flexíveis ou itens de grade podem criar contextos de empilhamento mesmo quando position
são static
.
Os itens flexíveis pintam exatamente da mesma forma que os blocos embutidos, exceto que a ordem de documento modificada por ordem é usada no lugar da ordem bruta de documento e
z-index
valores diferentes deauto
criar um contexto de empilhamento, mesmo queposition
sejastatic
.5.4 Ordenação do eixo Z: a
z-index
propriedadeA ordem de pintura dos itens de grade é exatamente igual aos blocos embutidos, exceto que a ordem de documento modificada pela ordem é usada no lugar da ordem bruta de documento e
z-index
valores diferentes deauto
criar um contexto de empilhamento, mesmo queposition
sejastatic
.
Aqui está uma demonstração do z-index
trabalho em itens flexíveis não posicionados: https://jsfiddle.net/m0wddwxs/
order
propriedade não é uma solução, pois se destina exclusivamente a alterar a ordem visual , portanto, não restaura a ordem semântica original que você é forçado a alterar em HTML para que esta solução alternativa funcione.
z-index
funcionará, mesmo quando "omg, não há position
especificado!", A especificação menciona o conceito de contexto de empilhamento , o que é bem explicado por este artigo no MDN
float: right
(ou qualquer outro meio de reverter a ordem, dos quais flex/order
tem poucos (menos?) Efeitos colaterais). Incitou dois violinos: demonstrando a float: right
abordagem , e demonstrandodirection: rtl
Eu tinha a mesma pergunta, mas depois tive um momento "duh". Em vez de escrever
x ~ y
Escreva
y ~ x
Obviamente, isso corresponde a "x" em vez de "y", mas responde a "existe uma correspondência?" pergunta, e uma simples passagem de DOM pode levá-lo ao elemento certo de forma mais eficiente do que fazer loop em javascript.
Sei que a pergunta original era CSS, portanto essa resposta provavelmente é completamente irrelevante, mas outros usuários de Javascript podem tropeçar na pergunta por meio de pesquisa, como eu fiz.
y ~ x
poderia resolver o meu problema
y ~ x
não responde a "existe uma correspondência?" pergunta, porque os dois seletores dados aqui significam coisas completamente diferentes. Não há como y ~ x
produzir uma correspondência, dada a subárvore, <root><x/><y/></root>
por exemplo. Se a pergunta é "você existe?" então o seletor é simplesmente y
. Se a pergunta é "y existe dado um irmão x em alguma posição arbitrária?" então você precisaria dos dois seletores. (Embora talvez eu esteja apenas procurando neste momento ...)
Dois truques . Invertendo basicamente a ordem HTML dos elementos desejados em HTML e usando o operador
~
Next siblings :
float-right
+ inverter a ordem dos elementos HTMLdiv{ /* Do with the parent whatever you know just to make the
inner float-right elements appear where desired */
display:inline-block;
}
span{
float:right; /* float-right the elements! */
}
span:hover ~ span{ /* On hover target it's "previous";) elements */
background:red;
}
<div>
<!-- Reverse the order of inner elements -->
<span>5</span>
<span>4</span>
<span>3</span>
<span>2</span>
<span>1</span>
</div>
direction: rtl;
+ inversa da ordem dos elementos internos.inverse{
direction: rtl;
display: inline-block; /* inline-block to keep parent at the left of window */
}
span:hover ~ span{ /* On hover target it's "previous";) elements */
background:gold;
}
Hover one span and see the previous elements being targeted!<br>
<div class="inverse">
<!-- Reverse the order of inner elements -->
<span>5</span>
<span>4</span>
<span>3</span>
<span>2</span>
<span>1</span>
</div>
+
é para o próximo irmão. Existe um equivalente para o irmão anterior?
!
e?
Existem 2 seletores de irmãos subsequentes no CSS convencional:
+
é o imediato seletor de irmão subsequente~
é o qualquer selector irmão subsequenteNo CSS convencional, não há seletor de irmãos anterior .
No entanto, na biblioteca pós-processador CSS de machado , existem 2 seletores de irmãos anteriores :
?
é o seletor de irmão anterior imediato (oposto a +
)!
é o seletor de qualquer irmão anterior (oposto a ~
)Exemplo de trabalho:
No exemplo abaixo:
.any-subsequent:hover ~ div
seleciona qualquer subseqüente div
.immediate-subsequent:hover + div
seleciona o subseqüente imediato div
.any-previous:hover ! div
seleciona qualquer anterior div
.immediate-previous:hover ? div
seleciona o anterior imediato div
div {
display: inline-block;
width: 60px;
height: 100px;
color: rgb(255, 255, 255);
background-color: rgb(255, 0, 0);
text-align: center;
vertical-align: top;
cursor: pointer;
opacity: 0;
transition: opacity 0.6s ease-out;
}
code {
display: block;
margin: 4px;
font-size: 24px;
line-height: 24px;
background-color: rgba(0, 0, 0, 0.5);
}
div:nth-of-type(-n+4) {
background-color: rgb(0, 0, 255);
}
div:nth-of-type(n+3):nth-of-type(-n+6) {
opacity: 1;
}
.any-subsequent:hover ~ div,
.immediate-subsequent:hover + div,
.any-previous:hover ! div,
.immediate-previous:hover ? div {
opacity: 1;
}
<h2>Hover over any of the blocks below</h2>
<div></div>
<div></div>
<div class="immediate-previous">Hover for <code>?</code> selector</div>
<div class="any-previous">Hover for <code>!</code> selector</div>
<div class="any-subsequent">Hover for <code>~</code> selector</div>
<div class="immediate-subsequent">Hover for <code>+</code> selector</div>
<div></div>
<div></div>
<script src="https://rouninmedia.github.io/axe/axe.js"></script>
Você pode usar a ordem inversa dos elementos em HTML. Além de usar order
como na resposta de Michael_B, você pode usar flex-direction: row-reverse;
ou flex-direction: column-reverse;
dependendo do seu layout.
Amostra de trabalho:
.flex {
display: flex;
flex-direction: row-reverse;
/* Align content at the "reversed" end i.e. beginning */
justify-content: flex-end;
}
/* On hover target its "previous" elements */
.flex-item:hover ~ .flex-item {
background-color: lime;
}
/* styles just for demo */
.flex-item {
background-color: orange;
color: white;
padding: 20px;
font-size: 3rem;
border-radius: 50%;
}
<div class="flex">
<div class="flex-item">5</div>
<div class="flex-item">4</div>
<div class="flex-item">3</div>
<div class="flex-item">2</div>
<div class="flex-item">1</div>
</div>
Não há uma maneira oficial de fazer isso no momento, mas você pode usar um pequeno truque para conseguir isso! Lembre-se de que é experimental e tem algumas limitações ... (verifique este link se estiver preocupado com a compatibilidade do navegador)
O que você pode fazer é usar um seletor CSS3: a pseudo classe chamada nth-child()
#list>* {
display: inline-block;
padding: 20px 28px;
margin-right: 5px;
border: 1px solid #bbb;
background: #ddd;
color: #444;
margin: 0.4em 0;
}
#list :nth-child(-n+4) {
color: #600b90;
border: 1px dashed red;
background: orange;
}
<p>The oranges elements are the previous sibling li selected using li:nth-child(-n+4)</p>
<div id="list">
<span>1</span><!-- this will be selected -->
<p>2</p><!-- this will be selected -->
<p>3</p><!-- this will be selected -->
<div>4</div><!-- this will be selected -->
<div>5</div>
<p>6</p>
<p>7</p>
<p>8</p>
<p>9</p>
</div>
:nth-child(-n+4)
é uma pseudo classe que precisa ser aplicada a um seletor para funcionar corretamente. Se você não é convencido, tente experimentá-lo usando um garfo do meu violino e verá que ele não funciona
*
seletor, mas é uma prática desagradável.
li#someListItem
e eu queria o (s) nó (s) logo antes (que é como eu interpreto "anterior") - não vejo como as informações que você forneceu podem me ajudar a expressar isso por meio do CSS. Você está apenas selecionando os primeiros n irmãos e suponha que eu conheça o n. Com base nessa lógica, qualquer seletor pode fazer o truque e selecionar o (s) elemento (s) que eu preciso (como: not ()).
Se você souber a posição exata, uma :nth-child()
exclusão baseada em todos os irmãos a seguir funcionaria.
ul li:not(:nth-child(n+3))
O que selecionaria todos os li
s antes do 3º (por exemplo, 1º e 2º). Mas, na minha opinião, isso parece feio e tem um caso de uso muito restrito.
Você também pode selecionar o enésimo filho da direita para a esquerda:
ul li:nth-child(-n+2)
O que faz o mesmo.
Não. Não é possível via CSS. Leva o "Cascade" ao coração ;-).
No entanto, se você conseguir adicionar JavaScript à sua página, um pouco de jQuery poderá levá-lo ao seu objetivo final.
Você pode usar o jQuery find
para executar um "olhar em frente" em seu elemento / classe / ID de destino e depois voltar para selecionar seu destino.
Então você usa o jQuery para reescrever o DOM (CSS) para seu elemento.
Com base nesta resposta de Mike Brant , o seguinte trecho de jQuery pode ajudar.
$('p + ul').prev('p')
Isso primeiro seleciona todos os <ul>
s que seguem imediatamente a <p>
.
Em seguida, "recua" para selecionar todos os <p>
s anteriores desse conjunto de <ul>
s.
Efetivamente, "irmão anterior" foi selecionado via jQuery.
Agora, use a .css
função para passar no seu CSS novos valores para esse elemento.
No meu caso, eu estava procurando uma maneira de selecionar um DIV com o id #full-width
, mas SOMENTE se ele tivesse um DIV descendente (indireto) com a classe de .companies
.
Eu tinha o controle de todo o HTML abaixo .companies
, mas não podia alterar nenhum do HTML acima dele.
E a cascata segue apenas 1 direção: para baixo.
Assim, eu poderia selecionar ALL #full-width
s.
Ou eu poderia selecionar .companies
que apenas seguisse a #full-width
.
Mas eu poderia não selecionar apenas #full-width
s que procedeu .companies
.
E, novamente, não consegui adicionar .companies
mais no HTML. Essa parte do HTML foi escrita externamente e envolveu nosso código.
Porém, com o jQuery, posso selecionar os #full-width
s necessários e atribuir o estilo apropriado:
$("#full-width").find(".companies").parents("#full-width").css( "width", "300px" );
Isso encontra tudo #full-width .companies
e seleciona apenas aqueles .companies
semelhantes à maneira como os seletores são usados para direcionar elementos específicos no padrão em CSS.
Em seguida, ele usa .parents
"backtrack" e seleciona TODOS os pais de .companies
,
mas filtra esses resultados para manter apenas #fill-width
elementos, para que, no final,
selecione apenas um #full-width
elemento se tiver um .companies
descendente de classe.
Por fim, atribui um novo width
valor CSS ( ) ao elemento resultante.
$(".parent").find(".change-parent").parents(".parent").css( "background-color", "darkred");
div {
background-color: lightblue;
width: 120px;
height: 40px;
border: 1px solid gray;
padding: 5px;
}
.wrapper {
background-color: blue;
width: 250px;
height: 165px;
}
.parent {
background-color: green;
width: 200px;
height: 70px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<div class="wrapper">
<div class="parent">
"parent" turns red
<div class="change-parent">
descendant: "change-parent"
</div>
</div>
<div class="parent">
"parent" stays green
<div class="nope">
descendant: "nope"
</div>
</div>
</div>
Target <b>"<span style="color:darkgreen">parent</span>"</b> to turn <span style="color:red">red</span>.<br>
<b>Only</b> if it <b>has</b> a descendant of "change-parent".<br>
<br>
(reverse cascade, look ahead, parent un-descendant)
</html>
Documentos de referência do jQuery:
$ () ou jQuery () : elemento DOM.
. find : obtenha os descendentes de cada elemento no conjunto atual de elementos correspondentes, filtrados por um seletor, objeto jQuery ou elemento.
. pais : obtenha o irmão imediatamente anterior de cada elemento no conjunto de elementos correspondentes. Se um seletor for fornecido, ele recuperará o irmão anterior apenas se corresponder a esse seletor (filtra os resultados para incluir apenas os elementos / seletores listados).
. css : defina uma ou mais propriedades CSS para o conjunto de elementos correspondentes.
previousElementSibling
).
previousElementSibling()
para aqueles que estão mais familiarizados com as funções JS DOM nativas, pode fornecer outro caminho não CSS.
+
seletor (inexistente) solicitado pelo OP. Considere esta resposta como um "hack" em JS. Está aqui para poupar o tempo que passei para encontrar uma solução.
Infelizmente, não há seletor de irmãos "anterior", mas é possível ainda obter o mesmo efeito usando posicionamento (por exemplo flutuador direita). Depende do que você está tentando fazer.
No meu caso, eu queria um sistema de classificação CSS de 5 estrelas. Eu precisaria colorir (ou trocar o ícone) das estrelas anteriores. Ao flutuar cada elemento corretamente, estou obtendo essencialmente o mesmo efeito (o html para as estrelas deve ser escrito "para trás").
Estou usando FontAwesome neste exemplo e trocando entre os unicodes de fa-star-o e fa-star http://fortawesome.github.io/Font-Awesome/
CSS:
.fa {
display: inline-block;
font-family: FontAwesome;
font-style: normal;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* set all stars to 'empty star' */
.stars-container {
display: inline-block;
}
/* set all stars to 'empty star' */
.stars-container .star {
float: right;
display: inline-block;
padding: 2px;
color: orange;
cursor: pointer;
}
.stars-container .star:before {
content: "\f006"; /* fontAwesome empty star code */
}
/* set hovered star to 'filled star' */
.star:hover:before{
content: "\f005"; /* fontAwesome filled star code */
}
/* set all stars after hovered to'filled star'
** it will appear that it selects all after due to positioning */
.star:hover ~ .star:before {
content: "\f005"; /* fontAwesome filled star code */
}
HTML: (40)
+
ou ~
seletores me parece o trabalho mais limpo.
Dependendo do seu objetivo exato, existe uma maneira de obter a utilidade de um seletor pai sem usar um (mesmo que exista) ...
Digamos que temos:
<div>
<ul>
<li><a>Pants</a></li>
<li><a>Socks</a></li>
<ul>
<li><a>White socks</a></li>
<li><a>Blue socks</a></li>
</ul>
</ul>
</div>
O que podemos fazer para que o bloco Meias (incluindo cores) se destaque visualmente usando espaçamento?
O que seria legal, mas não existe:
ul li ul:parent {
margin-top: 15px;
margin-bottom: 15px;
}
O que existe:
li > a {
margin-top: 15px;
display: block;
}
li > a:only-child {
margin-top: 0px;
}
Isso define todos os links de âncora para ter uma margem de 15px na parte superior e redefine para 0 para aqueles sem elementos UL (ou outras tags) dentro das LIs.
Eu precisava de uma solução para selecionar o irmão anterior tr. Eu vim com essa solução usando componentes React e Styled. Esta não é a minha solução exata (isso é da memória, horas depois). Eu sei que há uma falha na função setHighlighterRow.
OnMouseOver uma linha definirá o índice da linha para estado e renderizará a linha anterior com uma nova cor de plano de fundo
class ReactClass extends Component {
constructor() {
this.state = {
highlightRowIndex: null
}
}
setHighlightedRow = (index) => {
const highlightRowIndex = index === null ? null : index - 1;
this.setState({highlightRowIndex});
}
render() {
return (
<Table>
<Tbody>
{arr.map((row, index) => {
const isHighlighted = index === this.state.highlightRowIndex
return {
<Trow
isHighlighted={isHighlighted}
onMouseOver={() => this.setHighlightedRow(index)}
onMouseOut={() => this.setHighlightedRow(null)}
>
...
</Trow>
}
})}
</Tbody>
</Table>
)
}
}
const Trow = styled.tr`
& td {
background-color: ${p => p.isHighlighted ? 'red' : 'white'};
}
&:hover {
background-color: red;
}
`;
Não existe, e existe .
Se você deve colocar o rótulo antes da entrada, em vez disso, mantenha o rótulo e a entrada dentro de uma div e denomine a div da seguinte maneira:
.input-box {
display: flex;
flex-direction: column-reverse;
}
<div class="input-box">
<input
id="email"
class="form-item"
/>
<label for="email" class="form-item-header">
E-Mail*
</label>
</div>
Agora você pode aplicar as opções de estilo padrão para o próximo irmão disponíveis em css, e elas aparecerão como se você estivesse usando um estilo anterior para o irmão.
Eu tive um problema semelhante e descobri que todos os problemas dessa natureza podem ser resolvidos da seguinte maneira:
Dessa forma, você poderá estilizar seus itens atuais e anteriores (todos os itens substituídos pelos itens atuais e seguintes) e seus próximos itens.
exemplo:
/* all items (will be styled as previous) */
li {
color: blue;
}
/* the item i want to distinguish */
li.milk {
color: red;
}
/* next items */
li ~ li {
color: green;
}
<ul>
<li>Tea</li>
<li class="milk">Milk</li>
<li>Juice</li>
<li>others</li>
</ul>
Espero que ajude alguém.