Есть ли родительский селектор CSS? - PullRequest
2845 голосов
/ 18 июня 2009

Как выбрать элемент <li>, который является прямым родителем элемента привязки?

В примере мой CSS будет выглядеть примерно так:

li < a.active {
    property: value;
}

Очевидно, что есть способы сделать это с помощью JavaScript, но я надеюсь, что существует какой-то обходной путь, который существует в CSS уровня 2.

Меню, которое я пытаюсь стилизовать, издается CMS, поэтому я не могу переместить активный элемент в элемент <li> ... (если я не создаю тему модуля создания меню, который я бы предпочел не делает).

Есть идеи?

Ответы [ 30 ]

6 голосов
/ 19 марта 2019

Сейчас 2019 год, а в последнем варианте модуля вложенности CSS фактически есть что-то вроде этого. Представляем @nest at-rules.

3,2. Правило гнездования: @ nest

Хотя прямое вложение выглядит красиво, оно несколько хрупкое. Некоторые допустимые вложенные селекторы, такие как .foo &, запрещены, и редактирование селектора определенными способами может неожиданно сделать правило недействительным. Кроме того, некоторые люди считают, что гнездование сложно отличить визуально от окружающих объявлений.

Чтобы помочь во всех этих проблемах, эта спецификация определяет правило @nest, которое накладывает меньше ограничений на то, как правильно вкладывать правила стиля. Его синтаксис:

@nest = @nest <selector> { <declaration-list> }

Правило @nest функционирует идентично правилу стиля: оно начинается с селектора и содержит объявления, которые применяются к элементам, с которыми совпадает селектор. Единственное отличие состоит в том, что селектор, используемый в правиле @nest, должен содержать гнездо, что означает, что он содержит где-то вложенный селектор. Список селекторов содержит гнездо, если все его отдельные сложные селекторы содержат гнездо.

(скопируйте и вставьте с URL-адреса выше).

Пример допустимых селекторов согласно этой спецификации:

.foo {
  color: red;
  @nest & > .bar {
    color: blue;
  }
}
/* equivalent to
   .foo { color: red; }
   .foo > .bar { color: blue; }
 */

.foo {
  color: red;
  @nest .parent & {
    color: blue;
  }
}
/* equivalent to
   .foo { color: red; }
   .parent .foo { color: blue; }
 */

.foo {
  color: red;
  @nest :not(&) {
    color: blue;
  }
}
/* equivalent to
   .foo { color: red; }
   :not(.foo) { color: blue; }
 */
5 голосов
/ 01 августа 2018

Вот хак, используя pointer-events с hover:

<!doctype html>
<html>
	<head>
		<title></title>
		<style>
/* accessory */
.parent {
	width: 200px;
	height: 200px;
	background: gray;
}
.parent, 
.selector {
	display: flex;
	justify-content: center;
	align-items: center;
}
.selector {
	cursor: pointer;
	background: silver;
	width: 50%;
	height: 50%;
}
		</style>
		<style>
/* pertinent */
.parent {
	background: gray;
	pointer-events: none;
}
.parent:hover {
	background: fuchsia;
}
.parent 
.selector {
	pointer-events: auto;
}
		</style>
	</head>
	<body>
		<div class="parent">
			<div class="selector"></div>
		</div>
	</body>
</html>
5 голосов
/ 18 февраля 2017

Хотя в стандартном CSS в настоящее время нет родительского селектора, я работаю над (личным) проектом под названием ax (т. Е. расширенный синтаксис селектора CSS / ACSSSS ), среди его 7 новых селекторов, включает оба:

  1. непосредственный родительский селектор < (который позволяет выбор, противоположный >)
  2. и любой селектор предков ^ (который позволяет выбор, противоположный [SPACE])

ax в настоящее время находится на относительно ранней стадии разработки BETA.

Посмотреть демо здесь:

http://rounin.co.uk/projects/axe/axe2.html

(сравните два списка слева в стиле стандартных селекторов и два списка справа в стиле топоров)

4 голосов
/ 01 февраля 2018

По крайней мере, до CSS3, который вы не можете выбрать таким образом. Но в настоящее время это довольно легко сделать в JS, вам просто нужно добавить немного ванильного JavaScript, обратите внимание, что код довольно короткий.

      cells = document.querySelectorAll('div');
              [].forEach.call(cells, function (el) {
              //console.log(el.nodeName)
                if (el.hasChildNodes() && el.firstChild.nodeName=="A") {
                console.log(el)};
            });
            <div>Peter</div>
            <div><a href="#">Jackson link</a></div>
            <div>Philip</div>
            <div><a href="#">Pullman link</a></div>
3 голосов
/ 28 ноября 2015

Нет, вы не можете выбрать родителя только в css.

Но поскольку у вас уже есть класс .active, не проще ли переместить этот класс в li (вместо a)? Таким образом, вы можете получить доступ как к li, так и к a только через css.

2 голосов
/ 03 августа 2017

Это возможно с амперсандом в SASS:

h3
  font-size: 20px
  margin-bottom: 10px
  .some-parent-selector &
    font-size: 24px
    margin-bottom: 20px

Вывод CSS:

h3 {
  font-size: 20px;
  margin-bottom: 10px;
}
.some-parent-selector h3 {
  font-size: 24px;
  margin-bottom: 20px;
}
1 голос
/ 08 июня 2019

Есть идеи?

CSS 4 будет интересен, если он добавит несколько хуков в ходьбе назад . До тех пор можно (хотя не желательно) использовать checkbox и / или radio input s до break обычным образом, что вещи подключены, и через это также позволяют CSS работать за пределами своей обычной области ...

/* Hide things that may be latter shown */
.menu__checkbox__selection,
.menu__checkbox__style,
.menu__hidden {
  display: none;
  visibility: hidden;
  opacity: 0;
  filter: alpha(opacity=0); /* Old MS opacity */
}


/* Base style for content and style menu */
.main__content {
  background-color: lightgray;
  color: black;
}

.menu__hidden {
  background-color: black;
  color: lightgray;
  /* Make list look not so _listy_ */
  list-style: none;
  padding-left: 5px;
}

.menu__option {
  box-sizing: content-box;
  display: block;
  position: static;
  z-index: auto;
}

/* &#9660; - \u2630 - Three Bars */
/*
.menu__trigger__selection::before {
  content: '\2630';
  display: inline-block;
}
*/

/* &#9660; - Down Arow */
.menu__trigger__selection::after {
  content: "\25BC";
  display: inline-block;
  transform: rotate(90deg);
}


/* Customize to look more `select` like if ya like */
.menu__trigger__style:hover,
.menu__trigger__style:active {
  cursor: pointer;
  background-color: darkgray;
  color: white;
}


/**
 * Things to do when checkboxes/radios are checked
 */

.menu__checkbox__selection:checked + .menu__trigger__selection::after,
.menu__checkbox__selection[checked] + .menu__trigger__selection::after {
  transform: rotate(0deg);
}

/* This bit is something that ya may see elsewhere */
.menu__checkbox__selection:checked ~ .menu__hidden,
.menu__checkbox__selection[checked] ~ .menu__hidden {
  display: block;
  visibility: visible;
  opacity: 1;
  filter: alpha(opacity=100); /* MS!? */
}


/**
 * Hacky CSS only changes based off non-inline checkboxes
 * ... AKA the stuff you cannot unsee after this...
 */
.menu__checkbox__style[id="style-default"]:checked ~ .main__content {
  background-color: lightgray;
  color: black;
}

.menu__checkbox__style[id="style-default"]:checked ~ .main__content .menu__trigger__style[for="style-default"] {
  color: darkorange;
}


.menu__checkbox__style[id="style-one"]:checked ~ .main__content {
  background-color: black;
  color: lightgray;
}

.menu__checkbox__style[id="style-one"]:checked ~ .main__content .menu__trigger__style[for="style-one"] {
  color: darkorange;
}


.menu__checkbox__style[id="style-two"]:checked ~ .main__content {
  background-color: darkgreen;
  color: red;
}

.menu__checkbox__style[id="style-two"]:checked ~ .main__content .menu__trigger__style[for="style-two"] {
  color: darkorange;
}
    
    <!--
      This bit works but will one day cause troubles,
      but truth is ya can stick checkbox/radio inputs
      just about anywhere and then call them by id with
      a `for` label, keep scrolling to see what I mean
    -->
    <input type="radio"
           name="colorize"
           class="menu__checkbox__style"
           id="style-default">
    <input type="radio"
           name="colorize"
           class="menu__checkbox__style"
           id="style-one">
    <input type="radio"
           name="colorize"
           class="menu__checkbox__style"
           id="style-two">


<div class="main__content">

  <p class="paragraph__split">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
  </p>

  <input type="checkbox"
         class="menu__checkbox__selection"
         id="trigger-style-menu">
  <label for="trigger-style-menu"
         class="menu__trigger__selection"> Theme</label>

  <ul class="menu__hidden">
    <li class="menu__option">
      <label for="style-default"
             class="menu__trigger__style">Default Style</label>
    </li>

    <li class="menu__option">
      <label for="style-one"
             class="menu__trigger__style">First Alternative Style</label>
    </li>

    <li class="menu__option">
      <label for="style-two"
             class="menu__trigger__style">Second Alternative Style</label>
    </li>
  </ul>

  <p class="paragraph__split">
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>

</div>

... довольно брутто , но только с помощью CSS и HTML можно коснуться и снова прикоснуться к чему угодно, кроме body и :root практически из любого места, связав id и for свойства radio / checkbox input s и label триггеров ; Скорее всего, кто-то покажет, как снова прикоснуться к ним.

Еще одно предостережение заключается в том, что только один input определенного id может использоваться, сначала checkbox / radio выигрывает состояние переключения, другими словами. .. Но несколько меток могут указывать на один и тот же input, хотя это сделает и HTML, и CSS более грубыми.


... Я надеюсь, что существует какой-то обходной путь, свойственный CSS 2-го уровня ...

Не уверен насчет других : селекторов, но :checked для pre-CSS3, если я правильно помню, было что-то вроде [checked], поэтому вы можете найти его в приведенном выше коде, например ...

.menu__checkbox__selection:checked ~ .menu__hidden,
.menu__checkbox__selection[checked] ~ .menu__hidden {
 /* rules: and-stuff; */
}

... но такие вещи, как ::after и :hover Я совершенно не уверен, какая версия CSS появилась впервые.

С учетом всего вышесказанного, пожалуйста, никогда не используйте это в производстве, даже в гневе, как шутка, или другими словами, просто потому, что что-то может быть выполненным, не всегда означает должен .

0 голосов
/ 21 июня 2019

@ документ

Хотя технически он не является родительским селектором, он будет позволять вам выбирать URL страницы, который является "родительским" по мере поступления. Пожалуйста, имейте в виду, что вам нужно будет отстаивать это (см. Нижнюю часть этого поста для дальнейших инструкций). Я обновлю этот пост, как только этот метод станет жизнеспособным для веб-авторов.

Допустим, вы хотите изменить background-image навигационного заголовка для каждой страницы. Ваш HTML обычно будет выглядеть следующим образом:

<body>

<main id="about_"></main>

<header><nav></nav></header>

</body>

Добавление атрибута id к элементам head и body не является профессиональным и несовместимым с Web 3.0. Однако, выбрав URL , вам не нужно добавлять какой-либо HTML-код:

@document url('https://www.example.com/about/')
{
 body > header
 {
  background-image: url(about.png);
 }
}

Поскольку вы являетесь профессионалом (не так ли?), Вы всегда тестируете свой код локально перед его развертыванием на работающем сервере. Таким образом, статические URL не будут работать на localhost, 127.0.0.1, :1 и т. Д. - по умолчанию . Это означает, что если вы собираетесь успешно протестировать и проверить свой код, который вам понадобится для запуска серверных сценариев на вашем CSS. Это также подразумевает, что, если вы разрешаете пользователям запускать CSS на вашем сайте, вы должны обеспечить, чтобы их код CSS не мог запускать скрипты на стороне сервера, хотя ваш может. Большинство людей, которые сочли бы эту часть сообщения полезной, могут не знать, как к ней подойти, и все сводится к тому, как вы организуете свою рабочую среду.

  1. Всегда запускайте локальную среду на RAID 1, 5, 6, 1 + 0 или 0 + 1 (обычно ошибочно принимают за несуществующий «RAID 10», а 0 + 1 и 1 + 0 очень разные звери).
  2. Не храните свои работы ( и личные файлы) на том же диске, что и ваша ОС; вы будете переформатировать со временем, в настроении вы или нет.
  3. Ваш корневой путь должен выглядеть примерно так (на сервере WAMP (Windows, Apache, MariaDB и PHP)): D:\Web\Version 3.2\www.example.com\.
  4. В PHP вы начнете с $_SERVER['DOCUMENT_ROOT'] (вы можете определить ОС Linux с помощью условия if (substr($_SERVER['DOCUMENT_ROOT'],0,1) == '/') {}).
  5. Вы сохраняете копии старых версий, потому что вам нужны рабочие копии на случай, если вы что-то забыли и напортачили, отсюда и версия.

Следующее предполагает, что ваш действующий сервер использует www. (https://www.example.com/ вместо https://example.com/):

<?php
if (!isset($_SERVER['HTTP_HOST']))
{
//Client does not know what domain they are requesting, return HTTP 400.
}
else
{
 //Get the domain name.
 if (substr($_SERVER['HTTP_HOST'],0,4) === 'www.')
 {//Live Server
  $p0 = explode('www.',$_SERVER['HTTP_HOST'],2);
  $domain = $p0[1];
 }
 else
 {//localhost
  $p0 = explode('www.',$_SERVER['REQUEST_URI']);

  if (isset($p0[2]))
  {
   $p1 = explode('/',$p0[2],2);
   $domain = $p1[0];
  }
  else
  {
   $p1 = explode('/',$p0[1],2);
   $domain = $p1[0];
  }
 }


 //Now reconstruct your *relative* URL.
 if (isset($_SERVER['HTTPS'])) {$https = 'https';}
 else {$https = 'http';}

 $p0 = explode('www.',$_SERVER['HTTP_HOST']);

 if (stristr($_SERVER['HTTP_HOST'],'www.'))
 {
  $a = array('p1'=>$https.'://www.'.$domain, 'p2'=>'/');
 }
 else
 {
  $dir_ver = explode('/www.',$_SERVER['REQUEST_URI']);

  if ($_SERVER['HTTP_HOST']=='localhost' || $_SERVER['HTTP_HOST']==$_SERVER['SERVER_NAME'])
  {
   $p0 = explode($domain,$_SERVER['REQUEST_URI']);
   $a = array('p1'=>$https.'://'.$_SERVER['HTTP_HOST'], 'p2'=>htmlspecialchars($p0[0].$domain).'/');
  }
  else if (substr($_SERVER['HTTP_HOST'],0,7)=='192.168' || substr($_SERVER['HTTP_HOST'],0,4)=='127.')
  {
   $p0 = explode($domain,$_SERVER['REQUEST_URI']);
   $a = array('p1'=>$https.'://'.$_SERVER['HTTP_HOST'], 'p2'=>htmlspecialchars($p0[0].$domain).'/');
  }
 }

 print_r($a);
}
?>

$a вернет две части вашего URL. Корневой URL вашей главной страницы или веб-сайта будет /, поэтому примерно / будет about/ после того, как вы explode или split при сравнении строк. Это даст вам около 80% пути (как для локального, так и для живого тестирования), так что вы сможете запустить один и тот же код в обеих средах и использовать его в CSS для восстановления URL-адресов.

Поддержка браузера

Начиная с 2019 года только Gecko 61+ поддерживает эту функцию и только за флагом. Я уже защищал, что это становится пригодным для использования веб-авторами. Дэвид Барон является автором модуля условных правил CSS уровня 3 . Основная причина, по которой фактический CSS «родительский селектор» не существует, заключается в влиянии на производительность; этот метод сведет на нет влияние на производительность. Я также выступал за то, чтобы относительные URL-адреса поддерживались при наличии элемента HTML base. Если вы читаете это в 2019 году или вскоре после него (привет всем в 47 632 году!), Пожалуйста, first со ссылкой на следующие URL:

0 голосов
/ 13 июня 2019

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

<div className={`parent ${hasKiddos ? 'has-kiddos' : ''}`}>
    {hasKiddos && kiddos.map(kid => (
        <div key={kid.id} className="kid">kid</div>
    ))}
</div>

А потом просто:

.parent {
    color: #000;
}

.parent.has-kiddos {
    color: red;
}
0 голосов
/ 15 сентября 2016

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

$el.closest('.parent').css('prop','value');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...