El signo más ( +
) es para el próximo hermano.
¿Hay un equivalente para el hermano anterior?
El signo más ( +
) es para el próximo hermano.
¿Hay un equivalente para el hermano anterior?
Respuestas:
No, no hay un selector de "hermano anterior".
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.
Consulte Combinador de hermanos adyacentes de los selectores Nivel 3 y 5.7 Selectores de hermanos adyacentes de la Especificación de revisión de nivel 2 de hojas de estilo en cascada 2 (CSS 2.1) .
Encontré una forma de diseñar todos los hermanos anteriores (opuestos a ~
) que pueden funcionar dependiendo de lo que necesites.
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>
float:right
). Sí requirió un colapso de espacio en blanco entre unidades / palabras y relleno en lugar de márgenes, ¡pero funciona perfectamente de lo contrario!
Se presenta el selector de nivel 4:has()
(anteriormente el indicador de sujeto !
) que le permitirá seleccionar un hermano anterior con:
previous:has(+ next) {}
... pero al momento de escribir, está a cierta distancia más allá del límite de la compatibilidad con el navegador.
:has()
pseudoclase.
order
propiedad 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 order
propiedad flex puede mover elementos alrededor de 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
Haz ul
un contenedor flexible.
ul { display: flex; }
Invierta el orden de los hermanos en el marcado.
<ul>
<li>B</li>
<li>A</li>
</ul>
Use un selector de hermanos para seleccionar el Elemento A ( ~
o +
lo hará).
li:hover + li { background-color: red; }
Use la order
propiedad flex para restaurar el orden de los hermanos en la pantalla visual.
li:last-child { order: -1; }
...¡y voilá! 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 flexbox:
5.4. Orden de visualización: la
order
propiedadLos elementos flexibles se muestran y presentan de forma predeterminada en el mismo orden en que aparecen en el documento fuente. La
order
propiedad se puede usar para cambiar este orden.La
order
propiedad controla el orden en que aparecen los elementos flexibles dentro del contenedor flexible, asignándolos a grupos ordinales. Toma un solo<integer>
valor, que especifica a qué grupo ordinal pertenece el elemento flexible.
El order
valor inicial para todos los elementos flexibles es 0.
Ver también order
en la especificación de diseño de cuadrícula CSS .
Ejemplos de "selectores hermanos anteriores" creados con la order
propiedad 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>
Flexbox está destruyendo creencias arraigadas sobre CSS.
Una de esas creencias es que un selector de hermano anterior no es posible en CSS .
Decir que esta creencia es generalizada sería un eufemismo. Aquí hay una muestra de preguntas relacionadas con Stack Overflow solo:
Como se describió anteriormente, esta creencia no es del todo cierta. Un selector de hermanos anterior se puede simular en CSS utilizando la order
propiedad flex .
El z-index
mito
Otra creencia de larga data ha sido que z-index
solo funciona en elementos posicionados.
De hecho, la versión más actual de la especificación, el Borrador del Editor del W3C , aún afirma que esto es cierto:
9.9.1 Especificar el nivel de pila: la
z-index
propiedad
z-index
- Valor: auto | El | heredar
- Inicial: auto
- Se aplica a: elementos posicionados
- Heredado: no
- Porcentajes: N / A
- Medios: visual
- Valor calculado: como se especifica
(énfasis añadido)
En realidad, sin embargo, esta información es obsoleta e inexacta.
Los elementos que son elementos flexibles o elementos de cuadrícula pueden crear contextos de apilamiento incluso cuando position
es así static
.
Los elementos flexibles pintan exactamente igual que los bloques en línea, excepto que el orden del documento modificado se usa en lugar del orden del documento sin procesar y los
z-index
valores que no seanauto
crear un contexto de apilamiento, incluso siposition
es asístatic
.5.4. Ordenamiento del eje Z: la
z-index
propiedadEl orden de pintura de los elementos de la cuadrícula es exactamente el mismo que el de los bloques en línea, excepto que el orden del documento modificado se usa en lugar del orden del documento sin procesar y los
z-index
valores que no seanauto
crear un contexto de apilamiento, incluso siposition
es asístatic
.
Aquí hay una demostración de cómo z-index
trabajar en elementos flexibles no posicionados: https://jsfiddle.net/m0wddwxs/
order
propiedad no es una solución, ya que está destinada únicamente a cambiar el orden visual , por lo que no restaura el orden semántico original que se ve obligado a cambiar en HTML para que funcione esta solución alternativa.
z-index
funcionará, incluso cuando "¡Dios mío, no se position
especifica!", La especificación menciona el concepto de contexto de apilamiento , que se explica muy bien en este artículo sobre MDN
float: right
(o cualquier otro medio para revertir el orden, de los cuales flex/order
tiene pocos (¿menos?) Efectos secundarios). Batió dos violines: demostrando el float: right
enfoque y demostrandodirection: rtl
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 "¿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 de 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.
y ~ x
podría resolver mi problema
y ~ x
no responde "¿hay una coincidencia?" pregunta, porque los dos selectores dados aquí significan cosas completamente diferentes. No hay forma de que y ~ x
pueda producir una coincidencia dado el subárbol, <root><x/><y/></root>
por ejemplo. Si la pregunta es "¿existe y?" entonces el selector es simplemente y
. Si la pregunta es "¿existe y dado un hermano x en alguna posición arbitraria?" entonces necesitarías ambos selectores. (Aunque tal vez solo estoy
Dos trucos . Básicamente, invierte el orden HTML de tus elementos deseados en HTML y usa el operador
~
Hermanos siguientes :
float-right
+ invertir el orden de los 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;
+ 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 hermano anterior?
!
y?
Hay 2 selectores hermanos posteriores en CSS convencional:
+
es el selector de hermano posterior inmediato~
es la de cualquier selector de hermanos subsecuenteEn CSS convencional, no hay un selector de hermanos anterior .
Sin embargo, en la biblioteca de postprocesador CSS de ax , hay 2 selectores hermanos anteriores :
?
es el selector de hermano anterior inmediato (opuesto a +
)!
es el cualquier selector hermano anterior (opuesto ~
)Ejemplo de trabajo
En el siguiente ejemplo:
.any-subsequent:hover ~ div
selecciona cualquier posterior div
.immediate-subsequent:hover + div
selecciona el subsiguiente inmediato div
.any-previous:hover ! div
selecciona cualquier anterior div
.immediate-previous:hover ? div
selecciona el previo inmediato 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>
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! Recuerde que es experimental y tiene algunas limitaciones ... (consulte este enlace si le preocupa la compatibilidad del navegador)
Lo que puedes hacer es usar un selector CSS3: la pseudoclase llamada 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)
es una pseudo clase que debe aplicarse a un selector para que funcione correctamente. Si no está convencido, intente experimentarlo con un tenedor de mi violín y verá que no funciona
*
selector, pero es una práctica desagradable.
li#someListItem
y quería los nodos justo antes (que es como interpreto "anterior"). No veo cómo la información que proporcionó puede ayudarme a expresar eso a través de CSS. Solo estás seleccionando los primeros n hermanos, y supones que sé el n. Según esta lógica, cualquier selector puede hacer el truco y seleccionar los elementos que necesito (como: not ()).
Si conoce la posición exacta, funcionaría una :nth-child()
exclusión basada en todos los siguientes hermanos.
ul li:not(:nth-child(n+3))
Que seleccionaría todas las li
s antes de la 3ra (por ejemplo, 1ra y 2da). 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. No es posible a través de CSS. Lleva la "Cascada" al 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 jQuery's find
para realizar una "anticipación" en su elemento / clase / id de destino, luego retroceder para seleccionar su objetivo.
Luego usa jQuery para reescribir el DOM (CSS) para su elemento.
Según esta respuesta de Mike Brant , el siguiente fragmento de jQuery podría ayudar.
$('p + ul').prev('p')
Esto primero selecciona todos los correos <ul>
electrónicos que siguen inmediatamente a <p>
.
Luego "retrocede" para seleccionar todos los <p>
s anteriores de ese conjunto de <ul>
s.
Efectivamente, se ha seleccionado "hermano anterior" a través de jQuery.
Ahora, use la .css
función para pasar sus nuevos valores CSS para ese elemento.
En mi caso, estaba buscando encontrar una manera de seleccionar un DIV con la identificación #full-width
, pero SOLO si tenía un DIV descendiente (indirecto) con la clase de .companies
.
Tenía el control de todo el HTML debajo .companies
, pero no pude alterar ninguno de los HTML anteriores.
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 siguiera a #full-width
.
Pero podría no seleccionar sólo #full-width
de que procedieron .companies
.
Y, de nuevo, 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 los #full-width
s requeridos y luego asignar el estilo apropiado:
$("#full-width").find(".companies").parents("#full-width").css( "width", "300px" );
Esto encuentra todo #full-width .companies
y selecciona solo esos .companies
, de forma similar a cómo se usan los selectores para apuntar a elementos específicos en estándar en CSS.
Luego se usa .parents
para "retroceder" y seleccionar TODOS los padres de .companies
,
pero filtra esos resultados para mantener solo #fill-width
elementos, de modo que al final,
solo selecciona un #full-width
elemento si tiene un .companies
descendiente de clase.
Finalmente, asigna un nuevo width
valor CSS ( ) 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.
. find : obtiene 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 en el conjunto de elementos coincidentes. 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 : establece una o más propiedades CSS para el conjunto de elementos coincidentes.
previousElementSibling
).
previousElementSibling()
para aquellos más familiarizados con las funciones nativas de JS DOM podrían proporcionar otra ruta hacia adelante que no sea CSS.
+
selector (inexistente) que el OP solicitó específicamente. Considera esta respuesta como un "hack" de JS. Está aquí para ahorrarle a alguien el tiempo que pasé para encontrar una solución.
No hay ningún selector "anterior" hermanos por desgracia, pero se puede , posiblemente, aún así obtener el mismo efecto mediante el uso de posicionamiento (por ejemplo el derecho de flotación). Depende de lo que estés tratando de 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)
+
o los ~
selectores me parecen el trabajo más limpio.
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.
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 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;
}
`;
No hay y hay .
Si debe colocar la etiqueta antes de la entrada, en su lugar, coloque la etiqueta después de la entrada, mantenga la etiqueta y la entrada dentro de un div, y estilice el div de la siguiente manera:
.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>
Ahora puede aplicar las siguientes opciones de estilo estándar para hermanos disponibles en css, y parecerá que está utilizando un estilo de hermano anterior.
Tuve un problema similar y descubrí que todos los problemas de esta naturaleza se pueden resolver de la siguiente manera:
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.