Existe um seletor de "irmão anterior"?

1356

O sinal de mais ( +) é para o próximo irmão.

Existe um equivalente para o irmão anterior?

Jourkey
fonte
18
OMG, todas as respostas aqui sugerindo que você inverta a ordem dos elementos html e, em seguida, use CSS para fazê-los aparecer para trás, são um exagero. Claro que isso não é especificado na pergunta, mas a maioria das perguntas "você pode fazer X com CSS" deve assumir que você não pode alterar o HTML estruturalmente.
Squarecandy
3
@squarecandy, concordo principalmente com o seu comentário. Mas as soluções que você menciona como inadequadas são úteis em alguns casos (observe as votações anteriores). Então vale a pena postar. O que você vê como um "verdadeiro alongamento" pode ser uma "solução criativa" para os outros.
Michael Benjamin

Respostas:

839

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) .

cleto
fonte
14
Do padrão CSS3: Os elementos representados pelas duas sequências compartilham o mesmo pai na árvore de documentos e o elemento representado pela primeira sequência precede (não necessariamente imediatamente) o elemento representado pela segunda.
Lie Ryan
26
@ Ryan Ryan: Sim, mas o ponto principal da resposta é que você não seleciona o elemento anterior.
BoltClock
42
Aqui está um exemplo que fiz para ver o que isso pode e não pode fazer. jsfiddle.net/NuuHy/1
Abacus
7
A função jquery útil para isso é prev (). Por exemplo $ ("# the_element"). Prev (). Css ("background-color", "red")
Satbir Kira
1
Dependendo da sua marcação, isso pode ajudar: stackoverflow.com/questions/42680881/…
samnau
235

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>

manjar
fonte
17
Você pode adicionar uma explicação de como isso funciona. (parece que você aplicar um estilo para todos os itens e aos seguintes itens, mas pode De descrito explicitamente)
AL
1
Solução incrível. Não há necessidade de reordenar os elementos na marcação nem na renderização (via 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!
Steven Vachon
7
sim, mas um único anterior é necessário na maioria das vezes NÃO TODOS os anteriores!
Azerafati
42
Todos os links ficam vermelhos se eu passar o mouse sobre o espaço entre eles, para mim.
Lynn
3
@ Lynn a resposta inclui apenas o código para deixar os links anteriores em vermelho ao passar o mouse. Estilos adicionais dependem do seu caso de uso. Para um componente de classificação por estrelas (que eu acho que é um caso comum), você precisaria se livrar desse espaço e também tornar vermelho o link pairado.
precisa saber é
164

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.

Quentin
fonte
52
"Borda sangrenta para suporte ao navegador" pode ser um exagero. No momento em que escrevemos isso, nem mesmo a versão mais recente do Chrome pode usar a :has()pseudo-classe.
Reed Martin
33
@ReedMartin - é por isso que eu disse alguma distância para além da borda do sangramento
Quentin
12
": has não está marcado como parte do perfil do seletor dinâmico, o que significa que não pode ser usado nas folhas de estilo; somente com funções como document.querySelector ()." - developer.mozilla.org/pt-BR/docs/Web/CSS/:has
Arch Linux Tux
1
@ArchLinuxTux: "Esta limitação agora foi removida", portanto, uma vez antes, é possível usar esse recurso: D.
Jacob van Lingen
@JacobvanLingen - caniuse.com/#feat=css-has - Nenhum navegador suporta atualmente.
Quentin
153

Considere a orderpropriedade 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 orderpropriedade 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

  1. Faça ulum recipiente flexível.

    ul { display: flex; }

  1. Inverta a ordem dos irmãos na marcação.

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

  1. Use um seletor de irmão para direcionar o elemento A ( ~ou +fará).

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

  1. Use a orderpropriedade 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 orderpropriedade

Os itens flexíveis são, por padrão, exibidos e dispostos na mesma ordem em que aparecem no documento de origem. A orderpropriedade pode ser usada para alterar essa ordem.

A orderpropriedade 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 ordervalor inicial para todos os itens flexíveis é 0.

Veja também orderna especificação CSS Grid Layout .


Exemplos de "seletores de irmãos anteriores" criados com a orderpropriedade 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


Uma nota lateral - Duas crenças desatualizadas sobre CSS

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 orderpropriedade flex .

O z-indexMito

Outra crença de longa data tem sido que z-indexfunciona 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 positionsão static.

4.3 Pedido Z de item flexível

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-indexvalores diferentes de autocriar um contexto de empilhamento, mesmo que positionseja static.

5.4 Ordenação do eixo Z: a z-indexpropriedade

A 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-indexvalores diferentes de autocriar um contexto de empilhamento, mesmo que positionseja static.

Aqui está uma demonstração do z-indextrabalho em itens flexíveis não posicionados: https://jsfiddle.net/m0wddwxs/

Michael Benjamin
fonte
15
A orderpropriedade 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.
Marat Tanalin 20/03
2
@ Marat Tanalin: Para 90% dos casos de uso, assumindo que o suporte ao navegador não é um problema, isso funcionará perfeitamente. Os 10% restantes dos casos de uso são 1) casos em que alterar a ordem visual não é uma solução ou 2) casos que não envolvem CSS. Felizmente, para o número 2, os seletores-4 fornecem: has (), e cabe aos desenvolvedores das bibliotecas de seletores implementá-lo.
BoltClock
5
Lembre-se de que o CSS2.2 ED que você está citando ainda é, em essência, CSS2. E o flexbox e o layout da grade não existem no CSS2; no que diz respeito ao CSS2, essas informações certamente são verdadeiras. No mínimo, o texto pode ser atualizado para mencionar que o z-index pode ser aplicado a outros tipos de elementos em níveis futuros de CSS, da mesma forma que diz que outras propriedades podem estabelecer um contexto de empilhamento, como opacidade.
BoltClock
3
Caso alguém esteja tendo problemas para entender quando z-indexfuncionará, mesmo quando "omg, não há positionespecificado!", A especificação menciona o conceito de contexto de empilhamento , o que é bem explicado por este artigo no MDN
Rogier Spieker,
3
@Michael_B você é bem-vindo! Eu lidei com muitos front-end que desconhecem isso. Outra coisa que eu gostaria de mencionar, o seletor falso de irmãos anteriores também funciona bem com float: right(ou qualquer outro meio de reverter a ordem, dos quais flex/ordertem poucos (menos?) Efeitos colaterais). Incitou dois violinos: demonstrando a float: rightabordagem , e demonstrandodirection: rtl
Rogier Spieker
69

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.

Bryan Larsen
fonte
18
Acredito que funciona quando y pode ser encontrado facilmente. O problema é que y só pode ser encontrado em relação a x e, ao revertê-lo, você não pode encontrar y porque precisa encontrar x primeiro. É claro que isso se refere à questão de y ser o irmão anterior, e não o próximo, mas também pode se aplicar ao y ser o irmão seguinte.
David David
19
Você está sendo meio duro, Harsh. (desculpe, não pude resistir.) O ponto é que às vezes você só precisa saber "y existe?". Outras vezes, você pode usar ": before" para colocar algo entre os dois elementos. Finalmente, se você precisar entrar no jQuery, usar find ("y ~ x"). Prev () é mais fácil do que muitas alternativas.
Bryan Larsen
157
A ideia de um seletor de irmão anterior é que ele selecionará o elemento anterior. Infelizmente, revertê-lo, como descrito aqui, não fornece essa funcionalidade.
Zenexer 31/07/2013
14
Graças @Zenexer para o esclarecimento de que esta resposta não fornece uma solução real para a pergunta original, eu estava começando a sentir-me pensamento estúpido sobre como y ~ xpoderia resolver o meu problema
Jaime Hablutzel
4
Entendo a idéia por trás dessa resposta, no entanto, o raciocínio fornecido na resposta não faz muito sentido. O seletor y ~ xnão responde a "existe uma correspondência?" pergunta, porque os dois seletores dados aqui significam coisas completamente diferentes. Não há como y ~ xproduzir 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 ...)
BoltClock
25

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

Roko C. Buljan
fonte
25

+é para o próximo irmão. Existe um equivalente para o irmão anterior?

Você pode usar os dois seletores de machados :! e?

Existem 2 seletores de irmãos subsequentes no CSS convencional:

  • +é o imediato seletor de irmão subsequente
  • ~é o qualquer selector irmão subsequente

No 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>

Rounin
fonte
3
Isso me dá um erro de sintaxe quando tento implementá-lo no sass dentro de um projeto rails.
5287 alex
25
ax é um pós-processador CSS. Ele não usa a mesma sintaxe dos pré-processadores CSS, como Sass, Less ou Stylus.
Rounin
1
@Rounin você se importaria de adicionar alguns links de documentação? Não consigo encontrar o pós-processador de machado .
Dionys
@Dionys - Obrigado pelo seu interesse. ax é um projeto que iniciei no final de 2016, quando não conhecia o ES2015 e até mesmo objetos em JS eram muito novos para mim. O repositório do GitHub está aqui: github.com/RouninMedia/axe . Eu pretendo voltar a isso em algum momento (também desenvolvi algo chamado ax-blades, que é o equivalente em CSS de eventos javascript), mas preciso concluir meu trabalho em outro projeto (codinome ashiva ) primeiro.
Rounin
17

Outra solução flexbox

Você pode usar a ordem inversa dos elementos em HTML. Além de usar ordercomo 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>

Vadim Ovchinnikov
fonte
16

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>

Limitações

  • Você não pode selecionar elementos anteriores com base nas classes dos próximos elementos
  • É o mesmo para pseudo classes
0x1gene
fonte
1
@Ian porque :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
0x1gene
1
Na verdade, você pode se tornar independente do tipo de nó usando o *seletor, mas é uma prática desagradável.
Josh Burgess
1
Esta é a resposta que funcionou para mim, sem saber por que não foi votada mais alto ou aceita.
Jake Cattrall
1
Na verdade, ele funciona para nós diferentes: jsfiddle.net/aLhv9r1w/316 . Atualize a sua resposta :)
Jamie Barker
1
Eu tinha um seletor complexo, mas digamos que seja li#someListIteme 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 ()).
bitoolean 11/07/19
4

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 lis 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úcleo
fonte
3

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 findpara 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 .cssfunçã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-widths.
Ou eu poderia selecionar .companiesque apenas seguisse a #full-width.
Mas eu poderia não selecionar apenas #full-widths 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-widths necessários e atribuir o estilo apropriado:

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

Isso encontra tudo #full-width .companiese seleciona apenas aqueles .companiessemelhantes à 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-widthelementos, para que, no final,
selecione apenas um #full-widthelemento se tiver um .companiesdescendente de classe.
Por fim, atribui um novo widthvalor 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.

SherylHohman
fonte
Isso não tem nada a ver com a pergunta. Claro que é possível usar JS e você nem precisa do jQuery para isso ( previousElementSibling).
Fabian von Ellerts
1
@FabianvonEllerts Respondi à pergunta do OP diretamente na primeira linha da minha resposta. Como minha resposta afirma, literalmente não é possível via CSS . Forneci um caminho possível para alcançar o objetivo, usando uma tecnologia (JS | JQuery) à qual os usuários do CSS possam estar familiarizados e com acesso. Por exemplo, muitos sites WordPress também possuem JQuery, por isso é um ponto de entrada fácil: fácil de usar, lembrar e expandir. Seria irresponsável simplesmente responder NÃO , sem fornecer uma maneira alternativa de atingir a meta. Compartilhei o que aprendi e usei quando tive a mesma pergunta.
21819 SherlockHohman
previousElementSibling()para aqueles que estão mais familiarizados com as funções JS DOM nativas, pode fornecer outro caminho não CSS.
21819 SherlockHohman
Achei os outros CSS HACKS muito interessantes, mas, para meu caso de uso específico, eles não funcionaram (caíram na categoria de ressalvas) ou foram muito complicados. Para outros que se enquadram na mesma circunstância, é justo compartilhar esse método fácil de usar que pode funcionar, onde as soluções acima falham ou seria muito difícil de implementar / manter. Muitos CSS HACKS foram compartilhados. Este trabalho não foi coberto. Nenhuma das respostas usa o+ 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.
21719 SherlockHohman
2

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)

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

Andrew Leyva
fonte
1
flutuar para a direita e +ou ~seletores me parece o trabalho mais limpo.
Wylliam Judd
2

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.

DynamicDan
fonte
2

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;
    }
`;
kyle
fonte
0

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.

Ron16
fonte
-1

Eu tive um problema semelhante e descobri que todos os problemas dessa natureza podem ser resolvidos da seguinte maneira:

  1. dê um estilo a todos os seus itens.
  2. dê um estilo ao item selecionado.
  3. dê um estilo aos próximos itens usando + ou ~.

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.

Hejar
fonte
1
é basicamente o mesmo truque como na resposta mais velho do mesmo segmento: stackoverflow.com/a/27993987/717732
quetzalcoatl