Como afetar outros elementos quando um elemento é pairado

459

O que eu quero fazer é que quando um certo divé pairado, isso afetaria as propriedades de outro div.

Por exemplo, nesta demonstração do JSFiddle , quando você passa o mouse sobre #cubeele, muda o, background-colormas o que eu quero é que, quando passe o mouse #container, #cubeseja afetado.

div {
  outline: 1px solid red;
}
#container {
  width: 200px;
  height: 30px;
}
#cube {
  width: 30px;
  height: 100%;
  background-color: red;
}
#cube:hover {
  width: 30px;
  height: 100%;
  background-color: blue;
}
<div id="container">

  <div id="cube">
  </div>

</div>

Trufa
fonte

Respostas:

985

Se o cubo estiver diretamente dentro do contêiner:

#container:hover > #cube { background-color: yellow; }

Se o cubo estiver próximo (após a tag de fechamento dos contêineres), o contêiner:

#container:hover + #cube { background-color: yellow; }

Se o cubo estiver em algum lugar dentro do contêiner:

#container:hover #cube { background-color: yellow; }

Se o cubo for um irmão do contêiner:

#container:hover ~ #cube { background-color: yellow; }
Mike
fonte
107
Não se esqueça que o combinador geral de irmãos ~para 'cubo está em algum lugar após o contêiner no DOM e compartilha um pai'
robertc
3
Isso é bem legal. Existe alguma fonte onde eu possa encontrar mais informações sobre isso? É suportado por todos os navegadores, é CSS3? Seria ótimo ter mais algumas informações sobre isso. Muito obrigado!
Anónimo
2
+1 Ótima resposta @Mike. E se #containerfor o próximo #cube, ou seja, #containersegue #cube?
Peterka
4
O que fazer se o elemento pairado estiver dentro do contêiner (que queremos que seja efetuado) ??? Por exemplo: #cube: hover #container {Some CSS Effects}
Hanzallah Afgan 03/03
2
Boa resposta !! E se eu quiser mudar os pais quando passar o mouse pela criança. Eu acho que não há seletor para isso.
Mikel
41

Neste exemplo em particular, você pode usar:

#container:hover #cube {
    background-color: yellow;   
}

Este exemplo funciona apenas desde que cubeé filho de container. Para cenários mais complicados, você precisará usar CSS diferente ou JavaScript.

Emmett
fonte
35

O uso do seletor de irmãos é a solução geral para estilizar outros elementos ao passar o mouse sobre um determinado elemento, mas funciona apenas se os outros elementos seguirem o elemento especificado no DOM . O que podemos fazer quando os outros elementos devem realmente estar antes do pairar? Digamos que queremos implementar um widget de classificação da barra de sinal como o abaixo:

Widget de classificação da barra de sinal

Na verdade, isso pode ser feito facilmente usando o modelo flexbox CSS, configurando flex-directionpara reverse, para que os elementos sejam exibidos na ordem oposta à que estão no DOM. A captura de tela acima é de um widget implementado com CSS puro.

O Flexbox é muito bem suportado por 95% dos navegadores modernos.

Dan Dascalescu
fonte
Isso poderia ser editado para que o destaque não desapareça ao mover o mouse de uma barra para a outra? O piscar é um pouco perturbador.
Cerbrus
@ Cerbrus: Adicionada uma solução que não oculta o foco quando o mouse está entre as barras. A desvantagem é que a largura das barras não é mais igual.
Dan Dascalescu 9/09/15
1
Tente isso no seu primeiro trecho: .rating divborder-right: 4px solid white;
ative
1
Direcção Flex (não é bem suportado por Ie), ou 1) preto por padrão 2) tudo azul no rato ao longo do contentor 3) preto para próximo irmão na barra de pairar :)
Stephane Mathis
Eu fiz esse violino que (pelo menos para mim) tornou um pouco mais aparente sobre o que estava acontecendo aqui. jsfiddle.net/maxshuty/cj55y33p/3
maxshuty
8

Muito obrigado a Mike e Robertc por suas publicações úteis!

Se você possui dois elementos no HTML e deseja :hoversobrepor um e direcionar uma mudança de estilo no outro, os dois elementos devem estar diretamente relacionados - pais, filhos ou irmãos. Isso significa que os dois elementos devem estar um dentro do outro ou devem estar contidos no mesmo elemento maior.

Eu queria exibir definições em uma caixa no lado direito do navegador enquanto meus usuários liam o meu site e os :hovertermos destacados; portanto, não queria que o elemento 'definition' fosse exibido dentro do elemento 'text'.

Eu quase desisti e acabei de adicionar javascript à minha página, mas este é o futuro! Não devemos ter que tolerar o CSS e HTML nos dizendo onde devemos colocar nossos elementos para obter os efeitos desejados! No final, nos comprometemos.

Embora os elementos HTML reais no arquivo devam estar aninhados ou contidos em um único elemento para serem :hoverdestinos válidos um para o outro, o positionatributo css pode ser usado para exibir qualquer elemento onde você desejar. Eu usei position: Fixed para colocar o destino da minha :hoveração onde eu queria na tela do usuário, independentemente da sua localização no documento HTML.

O html:

<div id="explainBox" class="explainBox"> /*Common parent*/

  <a class="defP" id="light" href="http://en.wikipedia.or/wiki/Light">Light                            /*highlighted term in text*/
  </a> is as ubiquitous as it is mysterious. /*plain text*/

  <div id="definitions"> /*Container for :hover-displayed definitions*/
    <p class="def" id="light"> /*example definition entry*/ Light:
      <br/>Short Answer: The type of energy you see
    </p>
  </div>

</div>

O css:

/*read: "when user hovers over #light somewhere inside #explainBox
    set display to inline-block for #light directly inside of #definitions.*/

#explainBox #light:hover~#definitions>#light {
  display: inline-block;
}

.def {
  display: none;
}

#definitions {
  background-color: black;
  position: fixed;
  /*position attribute*/
  top: 5em;
  /*position attribute*/
  right: 2em;
  /*position attribute*/
  width: 20em;
  height: 30em;
  border: 1px solid orange;
  border-radius: 12px;
  padding: 10px;
}

Neste exemplo, o destino de um :hovercomando de um elemento dentro #explainBoxdeve ser #explainBoxou também dentro #explainBox. Os atributos de posição atribuídos a #definitions forçam a exibição no local desejado (fora #explainBox), mesmo que tecnicamente esteja localizado em uma posição indesejada no documento HTML.

Entendo que é considerado incorreto usar o mesmo #idpara mais de um elemento HTML; no entanto, neste caso, as instâncias de #lightpodem ser descritas independentemente, devido às suas respectivas posições em #idelementos exclusivos . Existe alguma razão para não repetir o id #lightcaso?

Rick
fonte
Muito pelo longa resposta por um curto ponto tal, mas aqui está uma jsFiddle dele jsfiddle.net/ubershmekel/bWgq6/1
ubershmekel
1
alguns navegadores surtam quando você usa as mesmas IDvárias vezes. Basta usar um class.
Serj Sagan
6

Só isso funcionou para mim:

#container:hover .cube { background-color: yellow; }

Onde .cubeestá CssClass do #cube.

Testado no Firefox , Chrome e Edge .

CyberHawk
fonte
4

Aqui está outra idéia que permite afetar outros elementos sem considerar nenhum seletor específico e usando apenas o :hoverestado do elemento principal.

Para isso, contarei com o uso de propriedades personalizadas (variáveis ​​CSS). Como podemos ler na especificação :

Propriedades personalizadas são propriedades comuns , portanto, podem ser declaradas em qualquer elemento, são resolvidas com as regras normais de herança e cascata ...

A idéia é definir propriedades customizadas no elemento principal e usá-las para estilizar elementos filhos e, como essas propriedades são herdadas, precisamos alterá-las no elemento principal ao passar o mouse.

Aqui está um exemplo:

#container {
  width: 200px;
  height: 30px;
  border: 1px solid var(--c);
  --c:red;
}
#container:hover {
  --c:blue;
}
#container > div {
  width: 30px;
  height: 100%;
  background-color: var(--c);
}
<div id="container">
  <div>
  </div>
</div>

Por que isso pode ser melhor do que usar o seletor específico combinado com o hover?

Posso fornecer pelo menos dois motivos que tornam este método um bom ponto a considerar:

  1. Se tivermos muitos elementos aninhados que compartilham os mesmos estilos, isso evitará um seletor complexo para segmentar todos eles em foco. Usando propriedades personalizadas, simplesmente alteramos o valor ao passar o mouse sobre o elemento pai.
  2. Uma propriedade customizada pode ser usada para substituir um valor de qualquer propriedade e também um valor parcial dela. Por exemplo, podemos definir uma propriedade personalizada para uma cor e podemos usá-lo dentro de um border, linear-gradient, background-color, box-shadowetc. Isso irá evitar nos zerando todas estas propriedades em foco.

Aqui está um exemplo mais complexo:

.container {
  --c:red;
  width:400px;
  display:flex;
  border:1px solid var(--c);
  justify-content:space-between;
  padding:5px;
  background:linear-gradient(var(--c),var(--c)) 0 50%/100% 3px no-repeat;
}
.box {
  width:30%;
  background:var(--c);
  box-shadow:0px 0px 5px var(--c);
  position:relative;
}
.box:before {
  content:"A";
  display:block;
  width:15px;
  margin:0 auto;
  height:100%;
  color:var(--c);
  background:#fff;
}

/*Hover*/
.container:hover {
  --c:blue;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
</div>

Como podemos ver acima, precisamos apenas de uma declaração CSS para alterar muitas propriedades de diferentes elementos.

Temani Afif
fonte