Pergunta

O sinal de mais (+) é para o próximo irmão. Existe um equivalente para o irmão anterior?

Foi útil?

Solução

Não, não há nenhuma selector "anterior irmão".

Em uma nota relacionada, ~ é para irmão geral sucessor (ou seja, o elemento vem depois de um presente, mas não necessariamente imediatamente depois) e é um seletor CSS3. + é para próximo irmão e é CSS2.1.

Consulte Adjacente irmão combinator de seletores Nível 3 e 5.7 seletores irmãos adjacentes de Cascading Style Sheets Nível 2 Revisão 1 (CSS 2.1) Especificação .

Outras dicas

Eu encontrei uma maneira de denominar todos os irmãos anteriores (em frente de ~) que pode funcionar, dependendo do que você precisa.

Vamos dizer que você tem uma lista de links e quando pairando em um, todos os anteriores deverá ficar vermelha. Você pode fazê-lo como este:

/* 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>

Seletores de nível 4 introduz :has() (anteriormente o ! indicador de assunto) que permitirá que você selecione um irmão anterior com:

previous:has(+ next) {}

... mas no momento da escrita, é uma certa distância para além da borda do sangramento para suporte ao navegador.

Considere a propriedade order de layouts flexíveis e grade.

eu vou focar flexbox nos exemplos abaixo, mas os mesmos conceitos se aplicam a Grid.


Com flexbox, um seletor irmão anterior pode ser simulado.

Em particular, a propriedade order Flex pode mover os elementos ao redor da tela.

Aqui está um exemplo:

Você quer elemento de à ficar vermelho quando o elemento B é passado.

<ul>
    <li>A</li>
    <li>B</li>
</ul>

PASSOS

  1. Faça o ul um recipiente flex.

    ul { display: flex; }
    

  1. Inverter a ordem de irmãos no mark-up.

    <ul>
       <li>B</li>
       <li>A</li>
    </ul>
    

  1. Use um seletor de irmão para alvo Elemento A (~ ou + vai fazer).

    li:hover + li { background-color: red; }
    

  1. Use a propriedade order flex para restaurar a ordem de irmãos no display visual.

    li:last-child { order: -1; }
    

... e voilà! Um seletor irmão anterior nasce (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>

A partir da especificação flexbox:

5.4. Ordem de exibição: a propriedade order

itens Flex são, por padrão, exibido e colocado para fora na mesma ordem em que aparecem no documento de origem. o propriedade order pode ser usado para mudar esta ordenação.

Os controles de propriedade order a ordem em que os itens flexíveis aparecem dentro do recipiente flexível, atribuindo-os a grupos ordinais. Leva um único valor <integer>, que especifica qual grupo ordinal do item Flex pertence.

O valor order inicial para todos os itens Flex é 0.

Veja também order na CSS disposição da grade de especificação .


Exemplos de "seletores irmão anterior" criadas com a propriedade order 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>

jsFiddle


Um Lado nota - duas crenças antiquadas sobre CSS

Flexbox está se quebrando crenças de longa data sobre CSS.

Uma tal crença é que um seletor irmão anterior não é possível em CSS .

Para dizer que esta crença é generalizada seria um eufemismo. Aqui está uma amostra de perguntas relacionadas no Stack Overflow sozinho:

Como descrito acima, esta crença não é inteiramente verdade. Um seletor irmão anterior pode ser simulado no CSS usando a propriedade order flex.

O z-index Mito

Outra crença de longa data tem sido que z-index funciona apenas em elementos posicionados.

Na verdade, a versão mais atual da especificação - o W3C do Editor projecto - ainda afirma que isto é verdade:

9.9.1 Especificando o nível de pilha: o z-index propriedade

z-index

  • Valor: automóvel | | herdar
  • inicial: auto
  • Aplica-se a: elementos posicionados
  • Herdado: não
  • Os percentuais: N / A
  • Mídia: visual
  • valor
  • Computed: conforme especificado

(ênfase adicionada)

Na realidade, no entanto, esta informação é obsoleto e impreciso.

Os elementos que são itens flexíveis ou itens grade pode criar empilhamento contextos mesmo quando position é static.

4.3. Flex item Z-ordenação

itens Flex pintar exatamente o mesmo que os blocos em linha, exceto que a ordem documento modificado de ordem é usado no lugar de matéria documento de ordem, e z-index diferentes auto valores criar um contexto de empilhamento mesmo se position é static.

5.4. Eixo Z Ordenação: a propriedade z-index

A ordem de pintura de itens grade é exatamente o mesmo como blocos in-line, exceto que a ordem documento modificado ordem é usado no lugar de ordem do documento cru, e outros que z-index valores auto criar um contexto de empilhamento mesmo se position é static.

Aqui está uma demonstração de trabalho z-index em itens não-posicionado Flex: https://jsfiddle.net/m0wddwxs/

Eu tive a mesma pergunta, mas então eu tive um momento "duh". Em vez de escrever

x ~ y

write

y ~ x

Obviamente, isso corresponde a "x" em vez de "y", mas responde à "há um jogo?" pergunta, e travessia de DOM simples pode levá-lo ao elemento direito de forma mais eficiente do que o looping em javascript.

Eu percebo que a pergunta original era uma pergunta CSS assim que esta resposta provavelmente é completamente irrelevante, mas outros usuários Javascript pode tropeçar sobre a questão através de pesquisa como eu fiz.

Dois truques . Basicamente invertendo a ordem HTML de seus elementos desejados em HTML e usando
~ Próxima irmãos do operador:

float-right + inversa a ordem dos elementos HTML

div{ /* 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>


pai com direction: rtl; + inversa a ordem dos elementos interiores

.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 a anterior irmão?

Você pode usar os dois ax seletores: ! e ?

Existem 2 seletores irmãos subseqüentes em CSS convencional:

  • + é a imediato seletor irmão posterior
  • ~ é a qualquer seletor irmão posterior

Em CSS convencional, existe não seletor irmão anterior .

No entanto, na ax biblioteca CSS pós-processador, existem 2 seletores irmão anterior :

  • ? é a imediato seletor irmão anterior (em frente de +)
  • ! é a qualquer seletor irmão anterior (em frente de ~)

Exemplo de Trabalho:

No exemplo abaixo:

  • seleciona .any-subsequent:hover ~ div qualquer div posterior
  • seleciona .immediate-subsequent:hover + div o div posterior imediato
  • seleciona .any-previous:hover ! div qualquer div anterior
  • seleciona .immediate-previous:hover ? div o div imediatamente anterior

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>

Outra solução flexbox

Você pode usar inversa a ordem dos elementos em HTML. Então, além de usar order como em resposta de Michael_B você pode usar flex-direction: row-reverse; ou flex-direction: column-reverse; dependendo do seu layout.

Exemplo 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á nenhuma maneira oficial de fazer isso no momento, mas você pode usar um pequeno truque para conseguir isso! Lembre-se que é experimental e tem algumas limitações ... (Verificação este link se você se preocupa com compatibilidade navegador)

O que você pode fazer é usar um seletor CSS3: a classe pseudo chamado 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>

Limitações

  • Você não pode selecionar elementos anteriores com base nas classes dos próximos elementos
  • Este é o mesmo para as classes pseudo

Se você sabe a posição exata uma exclusão baseada :nth-child() de todos os seguintes irmãos iria funcionar.

ul li:not(:nth-child(n+3))

Qual seria selecionar todos lis antes do terceiro (por exemplo, 1º e 2º). Mas, na minha opinião isso parece feio e tem uma usecase muito apertado.

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 há "anterior" irmão selector infelizmente, mas você pode possivelmente ainda obter o mesmo efeito usando posicionamento (por exemplo flutuador direita). Depende do que você está tentando fazer.

No meu caso, eu queria uma principalmente CSS sistema de classificação de 5 estrelas. Eu precisaria de cor (ou trocar o ícone de) as estrelas anteriores. Flutuando cada elemento certo, eu sou essencialmente recebendo o mesmo efeito (o html para as estrelas, portanto, devem ser escritos 'para trás').

Eu estou usando FontAwesome neste exemplo e trocando entre os Unicodes de fa-estrela-o e fa-estrela 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)

jsFiddle: http://jsfiddle.net/andrewleyva/88j0105g/

Dependendo do seu objetivo exato, há uma maneira de conseguir a utilidade de um seletor de pai sem o uso de um (mesmo que se existir) ...

Say 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 tornar o bloco Socks (incluindo cores meias) destacam-se visualmente utilizando espaçamento?

O que seria bom, 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 ter 15px margem na parte superior e redefine-lo de volta a 0 para aqueles com nenhum elemento UL (ou outras marcas) dentro LIs.

Eu tive um problema semelhante e descobri que todos problema desta natureza pode ser resolvido da seguinte forma:

  1. dar a todos os seus itens de um estilo.
  2. dar o seu item selecionado um estilo.
  3. dar próximos itens um estilo usando + ou ~.

e desta forma você vai ser capaz de estilo a sua atual, itens anteriores (todos os itens substituídos com itens atuais e próximas) e os 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.

No. Não é possível via CSS. Leva o "Cascade" ao coração; -).


No entanto, se você é capaz de adicionar JavaScript para sua página, um pouco de jQuery pode chegar ao seu objetivo final.
Você pode usar find do jQuery para realizar um "olhar em frente" no seu elemento de destino / classe / id, em seguida, recuar para selecionar o seu alvo.
Então você usar jQuery para re-escrever o DOM (CSS) para o seu elemento.

Com base esta resposta por Mike Brant , o seguinte trecho de jQuery poderia ajudar.

$('p + ul').prev('p')

Este primeiro seleciona todos os <ul>s que seguem imediatamente um <p>.
Então ele "Backtracks" para selecionar todos os <p>s anteriores daquele conjunto de <ul>s.

Com efeito, "irmão anterior" foi selecionado via jQuery.
Agora, usar a função .css para passar no seu CSS novos valores para esse elemento.


No meu caso eu estava olhando para encontrar uma maneira de selecionar um DIV com o #full-width id, mas somente se ele tinha uma DIV descendente (indireta) com a classe de .companies.

Eu tinha o controle de todo o HTML sob .companies, mas não conseguiu alterar qualquer do HTML acima dela.
Ea cascata vai apenas 1 direção:. Baixo

Assim que eu poderia selecionar TODAS #full-widths.
Ou eu poderia selecionar .companies que apenas seguiu um #full-width.
Mas eu poderia não selecionar apenas #full-widths que procedeu .companies.

E, novamente, eu era incapaz de adicionar .companies qualquer mais acima na HTML. Essa parte do HTML foi escrito externamente, e envolveu o nosso código.

Mas com jQuery, eu pode selecione os #full-widths necessários, em seguida, atribuir o estilo apropriado:

$("#full-width").find(".companies").parents("#full-width").css( "width", "300px" );

Este encontra todos #full-width .companies e seleciona apenas aqueles .companies, semelhante à forma como seletores são usados ??para elementos-alvo específicos no padrão em CSS.
Em seguida, ele usa .parents para "voltar atrás" e selecione todos os pais de .companies,
mas filtra esses resultados para manter apenas elementos #fill-width, de modo que, no final,
ele só seleciona um elemento #full-width se ele tem um descendente classe .companies.
Finalmente, ele atribui um valor novo CSS (width) para o 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>

jQuery Docs Referência:
$ () ou jQuery () :. elemento DOM < br> encontrar :. Obter os descendentes de cada elemento no conjunto atual de elementos combinados, filtrados por um seletor, objeto jQuery, ou elemento.
. pais : Obter o irmão imediatamente anterior, por cada elemento do conjunto de elementos combinados. Se um seletor é fornecido, ele recupera o irmão anterior somente se ele corresponde ao selector (filtra os resultados para incluir apenas os elementos enumerados / Selecção).
css :. Set uma ou mais propriedades CSS para o conjunto de elementos combinados.

Eu precisava de uma solução para selecionar o tr irmão anterior. Eu vim com essa solução usando reagir e de estilo componentes. Esta não é a minha solução exata (Isto é de memória, horas mais tarde). Eu sei que há uma falha na função setHighlighterRow.

OnMouseOver uma linha irá definir o índice de linha para estado, e são renderizados a linha anterior com uma nova cor 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;
    }
`;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top