it-roy-ru.com

CSS: Предотвращение получения родительского элемента: активный псевдокласс при нажатии на дочерний элемент

JSFiddle

Когда вы щелкаете по button, вы видите, что псевдокласс :active запускается для родительского div. Есть ли чистый CSS (или некоторая библиотека JS) способ псевдокласса :active не переключаться при нажатии button?

Я пробовал z-index, position: absolute & fixed и безуспешно.

27
knitevision

Из спецификации :

Селекторы не определяют, находится ли родительский элемент элемента «: active» или «: hover» также в этом состоянии.

Это означает, что это зависит от реализации. Если реализация решила действовать именно так (как, очевидно, делают нынешние браузеры), в стандарте нет ничего, что могло бы изменить это.

С CSS4 вы можете сделать:

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

но это еще не доступно и не доработано.

12
Amit

Если вы действительно хотите решить эту проблему с помощью CSS только:

Если ваша кнопка active, добавьте псевдоэлемент :before- и с помощью position: absolute; задайте фон перед: same, как у родителей.

button:active::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #eee;
    z-index: -1;
}

Теперь все, что нужно, это то, что родитель:

position: relative;
z-index: 0;

Посмотрите: http://jsfiddle.net/s0at4w4b/4/

Это not решает основную проблему, но является решением вашей текущей проблемы.

4
MMachinegun

Возможно, самый простой способ достичь того, что вы, вероятно, действительно хотите сделать, - это поместить не помещать кнопку в div, которую вы не хотите активировать.

Здесь у вас есть контейнер div, который содержит фон div (эквивалент родительского div в вашем исходном примере). Фон div имеет активное состояние отдельно от кнопки.

.container {
  position: relative;
  width: 200px;
  height: 200px;
}
.background {
  position: absolute;
  width: 100%;
  height: 100%;
  border: 1px solid black;
  background-color: #eee;
}
.background:active {
  background-color: red;
}
button {
  position: relative;
}
<div class="container">
  <div class="background"></div>
  <button>Click me!</button>
</div>

2
Alfred Xing

Я не думаю, что псевдо-класс :has будет когда-либо доступен в таблицах стилей. Если браузеры наконец решат реализовать его, это будет возможно только для JS API, таких как querySelector.

Тем не менее, у меня гораздо больше надежд на :focus-within , который, кажется, гораздо проще реализовать.

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

Конечно, это только предотвратит применение :active к #parent при нажатии на фокусируемый элемент, например кнопку. Вы можете сделать другие элементы фокусируемыми, добавив tabindex = "-1"

К сожалению, :focus-within не поддерживается широко, но вы можете использовать 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 не разрешает хотлинкинг, поэтому приведенный выше фрагмент может не работать, если вы не скопируете полифилл на свой сервер и не используете его.

1
Oriol

Вместо div:active {...} вы должны кодировать div:active:not(:hover) {...}, а background-color остается без изменений.

(старый фрагмент удален)

ОБНОВЛЕНИЕ

Чтобы сохранить основное поведение div и более общий подход, я обычно создаю несколько слоев.

Посмотрите фрагмент ниже, переключение на green просто для того, чтобы доказать, что оно работает, в то время как position и abolute пока просто и грязно:

#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

Псевдокласс: active применяется, когда элемент активируется пользователем. Например, между моментами, когда пользователь нажимает кнопку мыши и отпускает ее. В системах с более чем одной кнопкой мыши: активная применяется только к основной или основной кнопке активации (обычно это «левая» кнопка мыши) и любым их псевдонимам.

Могут существовать ограничения на язык документа или реализацию, в которых элементы могут стать активными. Например, [HTML5] определяет список активируемых элементов.

Родитель элемента, который соответствует: active, также соответствует: active. Так что, нет пути

0
Albert Navasardyan

вот решение jquery вместо использования псевдокласса 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

Это может или не может работать для вас, но именно так я добиваюсь этого с помощью чистого CSS. Единственное предостережение - это зависимость focus-within, которая не поддерживается IE или Edge.

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

Здесь происходит то, что родительский элемент получит активное состояние, как и дочерний элемент, по которому щелкают. Единственное отличие состоит в том, что фокус будет применяться к дочернему элементу, но только в следующем цикле. Чтобы обойти анимацию во время этого двухэтапного процесса, примените задержку в 1 мс. В следующем цикле элемент будет активен, но фокус будет применен к дочернему элементу. Таким образом, родитель не будет применять переход. Я думаю, что animation delay: 1ms будет работать так же.

Другой альтернативой является присвоение элементу атрибута tabindex=-1 и использование 

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

Единственная проблема, связанная с этим, заключается в том, что она может изменить поведение при навигации по клавиатуре, а также зависит от некоторого HTML. Если вы хотите использовать навигацию с помощью клавиатуры, используйте tabindex=0 или любое другое значение, кроме -1. Но JS не используется.

Существует несколько полифилов Nice для focus-within, которые вы можете использовать для IE/Edge, но они выходят за пределы «Только CSS».

Но мы можем соединить их вместе, чтобы создать это:

.parent {
  transition: background-color;
}

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

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

Это работает на IE11, Edge и Chrome.

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

0
ShortFuse

Насколько я знаю, активное состояние будет пузыриться. Таким образом, все родительские узлы будут иметь активное состояние.

Поэтому я сейчас не имею чисто CSS-решения. Вы можете избежать решения javascript (которое, как я полагаю, и есть то, что вам действительно нужно), изменив разметку так, чтобы div, имеющий активное состояние, больше не являлся родителем кнопки. Вы можете сделать их братьями и сестрами, например.

Затем CSS-часть этого решения исправляет макет, поэтому теперь он выглядит так же, как если бы он был родительским> дочерним.

Боюсь, я не смогу предложить вам более конкретного решения, не понимая, с чем вы работаете.

0
Harry Robbins

Псевдоэлементы CSS невероятно полезны - они позволяют нам создавать треугольники CSS для всплывающих подсказок и выполнять ряд других простых задач, предотвращая при этом необходимость в дополнительных элементах HTML. До сих пор эти свойства CSS псевдоэлемента были недоступны JavaScript, но теперь есть способ их получить!

Проверь это:

http://davidwalsh.name/pseudo-element

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

0
AsimRazaKhan

Кажется, нет никакого способа CSS справиться с этим делом. (не уверен насчет CSS4, как предложил Амит.) Итак, вот способ JQuery.

Идея в том, что вы управляете событиями mousedown и mouseup на 3 уровнях:

  1. родительский див
  2. кнопка, где вы не хотите, чтобы активное состояние распространялось на родительский div (".btn1" в примере ниже)
  3. любые другие дети, кроме кнопки во втором состоянии. («.btn2» в примере ниже)

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

попробуй это

hTML:

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

скрипт 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: включить файл библиотеки JQuery

0
becky1990