CSS: вложенный список - как выделить всю строку?

У меня есть вложенный список, как это:

   <ul class="tree">
     <li><div>Animals</div>
       <ul>
         <li><div>Birds</div>
           <ul>
             <li class="last"><div>Eagle</div></li>
           </ul>
         </li>
         <li><div>Mammals</div>
           <ul>
             <li><div>Elephant</div></li>
             <li class="last"><div>Cats</div>
               <ul>
                 <li><div>Lion</div></li>
                 <li class="last"><div>Tiger</div></li>
               </ul>
             </li>
           </ul>
         </li>
         <li class="last"><div>Reptiles</div>
           <ul>
             <li><div>Snake</li>
             <li class="last"><div>Turtle</div></li>
           </ul>
         </li>
       </ul>
     </li>
   </ul>

Я бы хотел, чтобы каждый уровень имел отступ, но я также хочу, чтобы каждая целая строка выделялась при наведении курсора. Когда я навожу курсор на DIV , выделение начинается только с левой позиции содержащего UL:

  ul.tree, ul.tree ul {
    list-style-type: none;
  }

  ul.tree li div:hover {
    background-color: red;
  }

Есть ли способ добиться желаемого эффекта без определения нескольких правил для li li, li li li и т. д.? Уровней вложенности может быть бесконечное количество, поэтому я считаю довольно уродливым определять все эти различные правила.

Или есть способ динамически вычислить уровень вложенности (в CSS?), чтобы я мог удалить отступы UL и вместо этого поместить правильное количество отступов внутри каждого DIV ?

ОБНОВЛЕНИЕ:

добавил скрипт, который показывает, что я хочу: http://jsfiddle.net/za3db/

Вы можете видеть, что это только на втором уровне, потому что я не определил правило для третьего или четвертого...


person Dylan    schedule 29.10.2013    source источник
comment
Можете ли вы опубликовать JSFiddle, который лучше отображает то, что вы имеете в виду под всей строкой?   -  person Wex    schedule 29.10.2013


Ответы (3)


Я не смог сделать это с помощью CSS, но это можно сделать с помощью небольшого количества javascript (jQuery).

$(".tree div").each(function()
{
    var padding = $(this).parents("ol, ul").length * 20 + "px";

    $(this).css("padding-left", padding);
});

Посмотреть этот jsFiddle

person Martin    schedule 29.10.2013
comment
Спасибо, это выглядит очень просто и понятно. Единственная «проблема» заключается в том, что я обнаружил, что для красивого отображения строк иерархии (например, в проводнике Windows на XP) UL должны иметь отступ. Но признаюсь, я не упомянул об этом в своем вопросе. - person Dylan; 30.10.2013
comment
@Dylan У меня есть аналогичная проблема, которую я ищу, ты случайно не решил ее с помощью css? - person jsduniya; 16.05.2020
comment
@jsduniya, вчера я опубликовал ответ, который, я думаю, поможет вам: stackoverflow.com/a/68268012/771466 - person Hayko Koryun; 07.07.2021

Это вроде как вам нужно: http://jsfiddle.net/za3db/4/

Он помещает псевдоэлемент с абсолютным позиционированием (left:0; right:0) под (z-index:-1) каждым из ваших div. Но у этой конструкции есть 2 минуса:

  • Это работает только тогда, когда вы знаете высоту div (в моем примере всегда 1.3em = высота строки)
  • Он не будет выделяться при наведении курсора на отступ, потому что div по-прежнему не начинается слева.

Таким образом, лучшим решением может быть javascript или просто запись всех этих li li, li li li, ... правил.


Редактировать: я немного поиграл с этим и придумал новую версию, используя скрытые плавающие counter()-псевдоэлементы для отступа: http://jsfiddle.net/za3db/5/.

person darthmaim    schedule 29.10.2013
comment
Спасибо за ваши усилия, это выглядит очень многообещающе. Есть идеи, работает ли он также в IE8 (поскольку jsfiddle.net, похоже, не работает в IE8)? - person Dylan; 30.10.2013
comment
Одна небольшая проблема: слишком длинные элементы переносятся на следующую строку и больше не имеют отступа. Я исправил это, добавив немного пробела: nowrap; , но из-за переполнения: hidden; горизонтальная полоса прокрутки не отображается, поэтому остальная часть элемента исчезает из поля зрения ... но с автоматическим переполнением он становится ОЧЕНЬ широким из-за заполнения и поля в 10000 пикселей ... - person Dylan; 30.10.2013

Я знаю, что этот ответ немного запоздал, однако недавно я работал над деревом, у меня была точно такая же мысль, и я нашел решение, изучив, как несколько продуктов решают эту проблему. Приведенный ниже фрагмент кода иллюстрирует возможное решение путем размещения заливки div для каждого элемента в дереве с большим отрицательным полем, позволяющим покрыть всю строку. Это очень простое CSS единственное решение.

Надеюсь, это поможет вам и другим, кто сталкивается с этим вопросом + ответом.

.fill {
  display: none;
  margin-left: -10000px;
  position: absolute;
  top: 0px;
  right: 0px;
  bottom: 0px;
  left: 0px;
  z-index: -1;
}

.title {
  position: relative;
}

.title:hover .fill {
  display: block;
  background-color: #eee;
}
<ul class="tree">
  <li>
    <div class="title">
      <div class="fill"></div>
      Animals
    </div>
    <ul>
      <li>
        <div class="title">
          <div class="fill"></div>
          Birds
        </div>
        <ul>
          <li class="last">
            <div class="title">
              <div class="fill"></div>
              Eagle
            </div>
          </li>
        </ul>
      </li>
      <li>
        <div class="title">
          <div class="fill"></div>
          Mammals
        </div>
        <ul>
          <li>
            <div class="title">
              <div class="fill"></div>
              Elephant
            </div>
          </li>
          <li class="last">
            <div class="title">
              <div class="fill"></div>
              Cats
            </div>
            <ul>
              <li>
                <div class="title">
                  <div class="fill"></div>
                  Lion
                </div>
              </li>
              <li class="last">
                <div class="title">
                  <div class="fill"></div>
                  Tiger
                </div>
              </li>
            </ul>
          </li>
        </ul>
      </li>
      <li class="last">
        <div class="title">
          <div class="fill"></div>
          Reptiles
        </div>
        <ul>
          <li>
            <div class="title">
              <div class="fill"></div>
              Snake
            </div>
          </li>
          <li class="last">
            <div class="title">
              <div class="fill"></div>
              Turtle
            </div>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

person Hayko Koryun    schedule 06.07.2021