web-dev-qa-db-fra.com

CSS: Empêcher l’élément parent d’obtenir: une pseudo classe active lorsque l’on clique sur l’élément enfant

JSFiddle

Lorsque vous cliquez sur button, vous constatez que la pseudoclasse :active est déclenchée pour le parent div. Existe-t-il un moyen CSS pur (ou une bibliothèque JS) de pseudo-classe :active ne basculant pas sur un clic button?

J'ai essayé z-index, position: absolute & fixed et sans succès.

27
knitevision

De la spec :

Les sélecteurs ne définissent pas si le parent d'un élément qui est ": actif" ou ": survolé" est également dans cet état.

Cela signifie que cela dépend de la mise en œuvre. Si une implémentation a choisi d'agir de cette manière (comme le font évidemment les navigateurs actuels), rien dans la norme ne peut changer cela.

Avec CSS4, vous pourrez peut-être:

.parent:active:not(:has(:active)) {
   color: red;
}

mais ce n'est ni disponible ni encore finalisé.

12
Amit

Je ne pense pas que la pseudo-classe :has sera un jour disponible dans les feuilles de style. Si les navigateurs décident finalement de l'implémenter, ce ne sera probablement que pour les API JS telles que querySelector.

Cependant, j'ai beaucoup plus d'espoir pour :focus-within , qui semble beaucoup plus simple à mettre en œuvre.

#parent:active:not(:focus-within) {
  background-color: red;
}

Bien entendu, cela empêchera uniquement l'application de :active à #parent lorsque vous cliquerez sur un élément activable comme un bouton. Vous pouvez rendre d'autres éléments focalisables en ajoutant tabindex = "-1"

Malheureusement, :focus-within n'est pas largement supporté, mais vous pouvez utiliser un JS polyfill .

#parent {
  border: 1px solid black;
  width: 300px;
  height: 300px;
}
#parent:active:not(.focus-within) {
  background-color: red;
}
<script src="https://Gist.githubusercontent.com/aFarkas/a7e0d85450f323d5e164/raw/"></script>
<div id="parent">
  <button>Click me</button>
  <p tabindex="-1">Or me</p>
</div>

Github n'autorise pas la création de liens hypertextes. Par conséquent, l'extrait de code ci-dessus risque de ne pas fonctionner à moins que vous copiez le fichier polyfill sur votre serveur et que vous l'utilisiez.

1
Oriol

Au lieu de div:active {...}, vous devriez coder div:active:not(:hover) {...} et le background-color reste inchangé.

(ancien extrait supprimé)

METTRE &AGRAVE; JOUR

Pour conserver le comportement principal div et une approche plus générique, je crée généralement plusieurs couches.

Vérifiez l'extrait de code ci-dessous, basculer sur green sert simplement à prouver que cela fonctionne alors que position et abolute sont juste rapides et sales pour l'instant:

#layer-data {
  width: 200px;
  height: 200px;
  background-color: #eee;
  border: 1px solid black;
}
#layer-data:active {
  background-color: red
}
#layer-btns:active {
  background-color: green
}
#layer-btns {
  z-index: 1;
  position: absolute;
  top: 1px;
  left: 1px;
  background: transparent;
  padding: 5px;
  width: auto;
  height: auto
}
#layer-data {
  z-index: 0;
  position: absolute;
  top: 0;
  left: 0;
  text-align: center;
  line-height: 200px
}
<div id="layer-btns">
  <button>Qlick me</button>
  <br/>
  <button>Qlick me too</button>
  <br/>
  <button>Qlick me three</button>
</div>

<div id="layer-data">
  some data-layer
</div>

0
Rene van der Lende

La pseudo-classe: active s'applique lorsqu'un élément est activé par l'utilisateur. Par exemple, entre les moments où l'utilisateur appuie sur le bouton de la souris et le relâche. Sur les systèmes dotés de plusieurs boutons de souris: Actif s'applique uniquement au bouton d'activation principal ou principal (généralement le bouton de souris "gauche"), ainsi qu'à ses alias.

Il peut y avoir des limites spécifiques au langage du document ou à la mise en œuvre sur lesquelles les éléments peuvent devenir: actifs. Par exemple, [HTML5] définit une liste d'éléments activables.

Le parent d'un élément qui correspond à: actif correspond également à: actif. Il n'y a donc aucun moyen

0
Albert Navasardyan

voici une solution jquery au lieu d'utiliser la pseudo-classe css :active

$(document).ready(function() {
    $('button').mousedown(function(e){
        e.stopPropagation();
        console.log('i got clicked');
    });

    $('div').mousedown(function(e){
        $('div').css('background', 'red')
    }).mouseup(function(e){
        $('div').css('background', '#eee')
    });
    $(document).mouseup(function(e){
        $('div').css('background', '#eee')
    });
});
div {
  width: 200px;
  height: 200px;
  background-color: #eee;
  border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <button>Qlick me</button>
</div>

0
indubitablee

Cela peut ou peut ne pas fonctionner pour vous, mais c’est comme cela que je le réalise avec du CSS pur. Le seul inconvénient est la dépendance de focus-within qui n'est pas prise en charge par IE ou Edge.

.parent {
  transition: background-color;
}
.parent:active:not(:focus-within) {
  background-color: red;      
  transition-delay: 1ms; // Delay one cycle to allow child to focus 
}

Ce qui se passe ici, c'est que l'élément parent obtiendra l'état actif, de même que l'enfant sur lequel l'utilisateur aura cliqué. La seule différence est que le focus s'appliquera à l'élément enfant, mais uniquement sur le cycle suivant. Pour contourner les animations de ce processus en 2 étapes, appliquez un délai de 1 ms. Au cycle suivant, l'élément sera actif, mais le focus sera appliqué à l'enfant. Ainsi, le parent n'appliquera pas la transition. J'imagine que animation delay: 1ms fonctionnerait de la même manière.

Une autre solution consiste à attribuer à l’élément un attribut tabindex=-1 et à l’utiliser. 

.parent {
  transition: background-color;
}
.parent:active:focus {
  background-color: red;      
}

Le seul problème avec ceci est le fait que cela peut changer le comportement de navigation du clavier et repose également sur du HTML. Si vous voulez utiliser le clavier, utilisez tabindex=0 ou une valeur autre que -1. Mais il n'y a pas de JS utilisé.

Il existe des polyfill sympas pour focus-within que vous pouvez utiliser pour IE/Edge, mais qui iraient en dehors de "CSS uniquement".

Mais, nous pouvons réunir les deux pour créer ceci:

.parent {
  transition: background-color;
}

.parent[tabindex]:active:focus {
  background-color: red;
}

.parent:active:not(:focus):not(:focus-within) {
  background-color: red;
  transition-delay: 1ms;
}

Cela fonctionne sur IE11, Edge et Chrome.

http://jsfiddle.net/s0at4w4b/42/

0
ShortFuse

Autant que je sache, l'état actif va bouillonner. Tous les nœuds parents auront donc un état actif.

Par conséquent, je ne fais pas maintenant d'une solution CSS pure. Vous pouvez éviter une solution javascript (ce que je suppose, c'est ce que vous cherchez vraiment), en modifiant le balisage de sorte que la div ayant un état actif ne soit plus un parent du bouton. Vous pouvez en faire des frères et soeurs, par exemple.

La partie CSS de cette solution est alors en train de corriger la mise en page, de sorte qu’il semble être la même chose maintenant qu’ils sont en train de sibilings comme ce qu’elle faisait quand ils étaient parent> enfant.

Je crains que je ne vous offre pas de solution plus spécifique sans voir ce que vous travaillez en train de bricoler.

0
Harry Robbins

Les pseudo-éléments CSS sont extrêmement utiles: ils nous permettent de créer des triangles CSS pour les info-bulles et d'effectuer un certain nombre d'autres tâches simples tout en évitant le recours à des éléments HTML supplémentaires. Jusqu'à présent, ces propriétés CSS de pseudo-éléments étaient inaccessibles par JavaScript, mais il existe maintenant une méthode pour les obtenir!

Vérifie ça:

http://davidwalsh.name/pseudo-element

http://davidwalsh.name/ways-css-javascript-interact

0
AsimRazaKhan

Il ne semble pas y avoir de moyen CSS pour gérer ce cas. (pas sûr de CSS4, comme suggéré par Amit.) Voici donc la méthode JQuery.

L'idée est de gérer les événements de souris et de souris à 3 niveaux:

  1. le parent div
  2. le bouton où vous ne voulez pas que l'état actif soit propagé à parent div (".btn1" dans l'exemple ci-dessous)
  3. tous les autres enfants sauf le bouton en deuxième condition. (".btn2" dans l'exemple ci-dessous)

JS Fiddle

HTML:

<div>
  <button class="btn1">Qlick me1</button>
  <button class="btn2">Qlick me2</button>
</div>

JQuery:

$(function(){
    $('div').each(function(e){
        $(this).mousedown(function(e){
            $(this).addClass("activeClass");
        }).mouseup(function(e){
            $(this).removeClass("activeClass");
        });
    });
    $('div .btn1').each(function(e){
        $(this).mousedown(function(e){
            e.stopPropagation();
        }).mouseup(function(e){
            e.stopPropagation();
        });
    });
    $('div :not(.btn1)').each(function(e){
        $(this).mousedown(function(e){
            $(this).parent().addClass("activeClass");
        }).mouseup(function(e){
            $(this).parent().removeClass("activeClass");
        });
    });
});

CSS:

div {
  width: 200px;
  height: 200px;
  background-color: #eee;
  border: 1px solid black;
}
.activeClass {
  background-color: red;
}
0
Vivek Athalye

essaye ça

html:

<div class="current" id="current">
  <button id="btnclick" >Qlick me</button>
</div>

script css:

div {
  width: 200px;
  height: 200px;
  background-color: #eee;
  border: 1px solid black;
}
.current_active{
  background-color: red;
}

jquery:

$("#btnclick").click(function(){
    $("#current").toggleClass("current_active");
});

JSFiddle

ps: inclure le fichier de bibliothèque jquery

0
becky1990