Pregunta

El signo más ( + ) es para el próximo hermano. ¿Hay un equivalente para el hermano anterior?

¿Fue útil?

Solución

No, no hay "hermano anterior" selector.

En una nota relacionada, ~ es para el hermano sucesor general (lo que significa que el elemento viene después de este, pero no necesariamente inmediatamente después) y es un selector CSS3. + es para el próximo hermano y es CSS2.1.

Ver Combinador de hermanos adyacentes de Selectores Nivel 3 y 5.7 Selectores de hermanos adyacentes de Especificaciones de hojas de estilo en cascada Nivel 2 Revisión 1 (CSS 2.1) .

Otros consejos

Encontré una forma de diseñar todos los hermanos anteriores (opuesto a ~ ) que puede funcionar dependiendo de lo que necesite.

Supongamos que tiene una lista de enlaces y al pasar el mouse sobre uno, todos los anteriores deberían volverse rojos. Puedes hacerlo así:

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

Los selectores de nivel 4 presentan : has () (anteriormente el indicador de asunto ! ) que le permitirá seleccionar un hermano anterior con:

previous:has(+ next) {}

& # 8230; pero al momento de escribir, está a cierta distancia más allá del límite para el soporte del navegador.

Considere la propiedad order de los diseños flex y grid.

Me centraré en flexbox en los ejemplos a continuación, pero los mismos conceptos se aplican a Grid.


Con flexbox, se puede simular un selector de hermanos anterior.

En particular, la propiedad flex order puede mover elementos por la pantalla.

Aquí hay un ejemplo:

  

Desea que el elemento A se ponga rojo cuando el elemento B está suspendido.

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

PASOS

  1. Convierta el ul en un contenedor flexible.

    ul { display: flex; }
    

  1. Invierte el orden de los hermanos en el marcado.

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

  1. Use un selector hermano para seleccionar el Elemento A ( ~ o + funcionará).

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

  1. Use la propiedad flex order para restaurar el orden de los hermanos en la pantalla visual.

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

... y voil & # 224 ;! Nace un selector de hermanos anterior (o al menos simulado).

Aquí está el 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>

De la especificación de flexbox:

  

5.4. Orden de visualización: la propiedad order

     

Los elementos flexibles se muestran y presentan de forma predeterminada en el mismo orden en que aparecen en el documento fuente. los   La propiedad order se puede usar para cambiar este orden.

     

La propiedad order controla el orden en que aparecen los elementos flexibles dentro del contenedor flexible, asignándolos a grupos ordinales. Toma un solo valor < integer > , que especifica qué grupo ordinal es el elemento flexible   pertenece a.

El valor inicial de order para todos los elementos flexibles es 0.

Consulte también order en el CSS Especificaciones de diseño de cuadrícula .


Ejemplos de " selectores de hermanos anteriores " creado con la propiedad flex order .

.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


Una nota al margen & # 8211; Dos creencias obsoletas sobre CSS

Flexbox está rompiendo creencias arraigadas sobre CSS.

Una de esas creencias es que un selector de hermano anterior no es posible en CSS .

Decir que esta creencia está muy extendida sería un eufemismo. Aquí hay una muestra de preguntas relacionadas con Stack Overflow solo:

Tenía la misma pregunta, pero luego tuve un '' duh '' momento. En lugar de escribir

x ~ y

escribir

y ~ x

Obviamente esto coincide con "x" en lugar de "y", pero responde a "¿hay una coincidencia?" pregunta, y el simple recorrido del DOM puede llevarlo al elemento correcto de manera más eficiente que hacer un bucle en JavaScript.

Me doy cuenta de que la pregunta original era una pregunta CSS, por lo que esta respuesta probablemente sea completamente irrelevante, pero otros usuarios de Javascript pueden tropezar con la pregunta a través de la búsqueda como lo hice yo.

Dos trucos . Básicamente, invierte el orden HTML de tus elementos deseados en HTML y usa
~ Siguiente hermano operador:

float-right + invierte el orden de los 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>


Principal con dirección: rtl; + invertir el orden de los 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>

  

+ es para el próximo hermano. ¿Hay un equivalente para el anterior   hermano?

Puede usar los dos selectores ax : ! y ?

Hay 2 subsecuentes selectores de hermanos en CSS convencional:

  • + es el selector de hermanos subsiguiente inmediato
  • ~ es el any selector de hermano posterior

En CSS convencional, no hay ningún selector de hermanos anterior .

Sin embargo, en la biblioteca de postprocesador CSS ax , hay 2 selectores de hermanos anteriores :

  • ? es el selector de hermano anterior inmediato (opuesto a + )
  • ! es el selector de hermanos anterior any (opuesto a ~ )

Ejemplo de trabajo:

En el siguiente ejemplo:

  • .any-later: hover ~ div selecciona cualquier div
  • .immediate -fter: hover + div selecciona el div
  • inmediato posterior
  • .any-previous: hover! div selecciona cualquier div
  • anterior
  • .immediate-previous: ¿pasar el mouse? div selecciona el div
  • anterior inmediato

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>

Otra solución de flexbox

Puede usar el orden inverso de los elementos en HTML. Luego, además de usar order como en la respuesta de Michael_B puede usar flex-direction: row -reverse; o flex-direction: column-reverse; según su diseño.

Muestra de trabajo:

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

No hay una forma oficial de hacerlo en este momento, ¡pero puedes usar un pequeño truco para lograrlo! Recuerda que es experimental y tiene alguna limitación ... (consulte este enlace si le preocupa la compatibilidad del navegador)

Lo que puede hacer es usar un selector CSS3: el pseudoclase llamado 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>

Limitaciones

  • No puede seleccionar elementos anteriores en función de las clases de los siguientes elementos
  • Esto es lo mismo para las pseudo clases

Si conoce la posición exacta, una exclusión basada en : nth-child () de todos los siguientes hermanos funcionaría.

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

Que seleccionaría todos los li s antes del tercero (por ejemplo, primero y segundo). Pero, en mi opinión, esto se ve feo y tiene un caso de uso muy estricto.

También puede seleccionar el enésimo hijo de derecha a izquierda:

ul li:nth-child(-n+2)

Que hace lo mismo.

No hay " anterior " Desafortunadamente, el selector de hermanos, pero todavía puede posiblemente obtener el mismo efecto utilizando el posicionamiento (por ejemplo, flotar a la derecha). Depende de lo que intentes hacer.

En mi caso, quería un sistema de calificación de 5 estrellas CSS principalmente. Necesitaría colorear (o intercambiar el ícono) de las estrellas anteriores. Al flotar cada elemento a la derecha, esencialmente obtengo el mismo efecto (por lo tanto, el html para las estrellas debe escribirse 'al revés').

Estoy usando FontAwesome en este ejemplo y cambio entre los unicodes de fa-star-o y 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/

Dependiendo de su objetivo exacto, hay una manera de lograr la utilidad de un selector principal sin usar uno (incluso si existiera uno) ...

Digamos que tenemos:

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

¿Qué podemos hacer para que el bloque Socks (incluidos los colores de los calcetines) se destaque visualmente usando el espaciado?

Lo que sería bueno pero no existe:

ul li ul:parent {
  margin-top: 15px;
  margin-bottom: 15px;
}

Qué existe:

li > a {
  margin-top: 15px;
  display: block;
}
li > a:only-child {
  margin-top: 0px;
}

Esto establece que todos los enlaces de anclaje tengan un margen de 15 píxeles en la parte superior y lo restablece a 0 para aquellos sin elementos UL (u otras etiquetas) dentro de las LI.

Tuve un problema similar y descubrí que todos los problemas de esta naturaleza se pueden resolver de la siguiente manera:

  1. dale un estilo a todos tus artículos.
  2. dale un estilo al elemento seleccionado.
  3. dale un estilo a los siguientes elementos usando + o ~.

y de esta manera podrá diseñar sus elementos anteriores actuales (todos los elementos anulados con los elementos actuales y siguientes) y sus elementos siguientes.

ejemplo:

/* 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 ayude a alguien.

No. No es posible a través de CSS. Se necesita la "Cascada" de corazón ;-).


Sin embargo, si puede agregar JavaScript a su página, un poco de jQuery podría llevarlo a su objetivo final.
Puede usar el find de jQuery para realizar un "look-ahead". en su elemento / clase / id de destino, luego retroceda para seleccionar su objetivo.
Luego, usa jQuery para volver a escribir el DOM (CSS) para su elemento.

Basado en esta respuesta de Mike Brant , el siguiente fragmento de jQuery podría ayudar.

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

Esto primero selecciona todos los < ul > s que siguen inmediatamente a un < p > .
Luego se '' retrocede '' para seleccionar todos los < p > s anteriores de ese conjunto de < ul > s.

Efectivamente, "hermano anterior" ha sido seleccionado a través de jQuery.
Ahora, use la función .css para pasar sus nuevos valores CSS para ese elemento.


En mi caso, buscaba la forma de seleccionar un DIV con el id # full-width , pero SOLO si tenía un DIV descendiente (indirecto) con la clase de .companies .

Tuve el control de todo el HTML en .companies , pero no pude alterar ninguno de los HTML encima.
Y la cascada solo va en 1 dirección: hacia abajo.

Por lo tanto, podría seleccionar TODOS # full-width s.
O podría seleccionar .companies que solo siguió a un # full-width .
Pero podría no seleccionar solo # full-width s que procedió .companies .

Y, nuevamente, no pude agregar .companies más arriba en el HTML. Esa parte del HTML se escribió externamente y envolvió nuestro código.

Pero con jQuery, puedo seleccionar el # full-width s requerido, y luego asignar el estilo apropiado:

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

Esto encuentra todas las # compañías de ancho completo , y selecciona solo esas .companies , de forma similar a cómo se usan los selectores para apuntar a elementos específicos en estándar en CSS. < br> Luego usa .parents para " retroceder " y seleccione TODOS los padres de .companies ,
pero filtra esos resultados para mantener solo los elementos # fill-width , de modo que, al final,
solo selecciona un elemento # full-width si tiene un descendiente de clase .companies .
Finalmente, asigna un nuevo valor CSS ( width ) al 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 referencia de jQuery:
$ () o jQuery () : elemento DOM. < br> . find : Obtenga los descendientes de cada elemento en el conjunto actual de elementos coincidentes, filtrados por un selector, un objeto jQuery o un elemento.
. padres : Obtenga el hermano inmediatamente anterior de cada elemento del conjunto de elementos combinados. Si se proporciona un selector, recupera el hermano anterior solo si coincide con ese selector (filtra los resultados para incluir solo los elementos / selectores enumerados).
. css : establezca una o más propiedades CSS para el conjunto de elementos combinados.

Necesitaba una solución para seleccionar el hermano anterior tr. Se me ocurrió esta solución usando React y Styled-components. Esta no es mi solución exacta (esto es de memoria, horas después). Sé que hay una falla en la función setHighlighterRow.

OnMouseOver una fila establecerá el índice de la fila en estado y volverá a procesar la fila anterior con un nuevo color de fondo

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top