Почему flexbox влияет на маркер содержащего элемента списка? - PullRequest
0 голосов
/ 31 января 2019

Зная, что элемент a list-item не может быть одновременно display: flex , я обертываю содержимое контейнером, затем помещаю контейнер внутрь <li />.

* 1007.* Все идет хорошо для элементов с контентом.Однако, если первый элемент в контейнере не имеет дочерних узлов, маркер <li /> неожиданно расположен внизу.

Хотя в моем случае я могу просто добавить display: none к обходному пути, яЯ все еще в замешательстве: Как содержимое во flexbox может повлиять на его узел бабушки и дедушки?

Пример: (маркер 1. расположен в правом нижнем углу <li />)

.flex { display: flex; }
<ol style="width: 15em">
    <li>
        <div class="flex">
            <div></div>
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
        </div>
    </li>
    <li>
        <div class="flex">
            <div>TITLE</div>
            <div>If there's content in the first element, then it goes as expected.</div>
        </div>
    </li>
    <li>
        <div class="flex">
            <div>It's also fine if there's only one child here.</div>
        </div>
    </li>
</ol>

В связи с этим вопрос: псевдоэлемент CSS ::marker не реализован в популярных браузерах, и только Firefox поддерживает @ counter-style .На данный момент, что рекомендуется для реализации пользовательских маркеров в <ol />?(Я видел некоторых людей, использующих ::before для этого, чтобы заставить пользователя НЕ копировать текст маркера. Но я не знаю, хорошо это или нет.)

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Чтобы устранить проблему, просто отрегулируйте выравнивание по базовой линии: (другое решение в конце)

.flex {
  display: flex;
  align-items:baseline;
}
<ol style="width: 15em">
  <li>
    <div class="flex">
      <div></div>
      <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>TITLE</div>
      <div>If there's content in the first element, then it goes as expected.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>It's also fine if there's only one child here.</div>
    </div>
  </li>
</ol>

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

.flex {
  display: flex;
}
div:empty {
  width:30px;
  background:red;
}
<ol style="width: 15em">
  <li>
    <div class="flex">
      <div></div>
      <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>TITLE</div>
      <div>If there's content in the first element, then it goes as expected.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>It's also fine if there's only one child here.</div>
    </div>
  </li>
</ol>

Пустой элемент растягивается из-за выравнивания по умолчанию, а затем нумерация выравнивается по его низу.

Если вы увеличиваете / уменьшаетеВысота вы лучше заметите это

.flex {
  display: flex;
}
div:empty {
  width:30px;
  background:red;
  animation:change 5s linear infinite alternate;
}
@keyframes change {
   from {
     height:5px;
   }
   to  {
     height:80px;
   }
}
<ol style="width: 15em">
  <li>
    <div class="flex">
      <div></div>
      <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>TITLE</div>
      <div>If there's content in the first element, then it goes as expected.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>It's also fine if there's only one child here.</div>
    </div>
  </li>
</ol>

Это также произойдет, если у вас, например, элемент inline-block внутри первого элемента Flex установлен на overlow:hidden (делая его базовую линию нижней границей)

.flex {
  display: flex;
}
div:empty {
  width:30px;
  background:red;
}
.inline-block {
  display:inline-block;
  height:50px;
  background:green;
  width:50px;
  overflow:hidden;
}
<ol style="width: 15em">
  <li>
    <div class="flex">
      <div></div>
      <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div><div class="inline-block">some text </div></div>
      <div>TITLE</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>It's also fine if there's only one child here.</div>
    </div>
  </li>
</ol>

В основном нумерация пытается выровняться с базовой линией первого элемента.Если вы увеличите font-size первого элемента, мы также можем заметить это:

.flex {
  display: flex;
}
.size {
  animation:change 5s linear infinite alternate;
}
@keyframes change {
   from {
     font-size:5px;
   }
   to  {
     font-size:30px;
   }
}
<ol style="width: 15em">
  <li>
    <div class="flex">
      <div></div>
      <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div class="size">TITLE</div>
      <div>If there's content in the first element, then it goes as expected.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>It's also fine if there's only one child here.</div>
    </div>
  </li>
</ol>

Как вы уже заметили, это происходит только в том случае, если речь идет о первом элементе, который делает это немного сложным и непростым объяснением:

.flex {
  display: flex;
}
div:empty {
  width:30px;
  background:red;
}
.inline-block {
  display:inline-block;
  height:50px;
  background:green;
  width:50px;
  overflow:hidden;
}
<ol style="width: 15em">
  <li>
    <div class="flex">
      <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
      <div></div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>TITLE</div>
      <div><div class="inline-block">some text </div></div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>It's also fine if there's only one child here.</div>
    </div>
  </li>
</ol>

Другой обходной путь в дополнение к изменению выравнивания заключается в рассмотрении псевдоэлемента внутри контейнера flexbox, который будет нашим первым элементом flex, поэтому мы избегаем любого взаимодействия с нашим real elements.

Хитрость заключается в том, чтобы сохранить этот элемент не пустым, а по крайней мере с содержимым.Я использовал символ пробела нулевой ширины \200B:

.flex {
  display: flex;
}
.flex:before {
  content:"\200B"; /*a non collapsible white space*/ 
}
div:empty {
  width:30px;
  background:red;
  animation:change 5s linear infinite alternate;
}
@keyframes change {
   from {
     height:5px;
   }
   to  {
     height:80px;
   }
}
.size {
  color:green;
  animation:size 5s linear infinite alternate;
}
@keyframes size {
   from {
     font-size:5px;
   }
   to  {
     font-size:20px;
   }
}
<ol style="width: 15em">
  <li>
    <div class="flex">
      <div></div>
      <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div class="size">TITLE</div>
      <div>If there's content in the first element, then it goes as expected.</div>
    </div>
  </li>
  <li>
    <div class="flex">
      <div>It's also fine if there's only one child here.</div>
    </div>
  </li>
</ol>
0 голосов
/ 31 января 2019

Я не уверен, что вы пытаетесь достичь с помощью flexbox внутри элемента, но пустой элемент внутри flex-сгиба сворачивается вниз, так что это странным образом влияет на вещи.Вы исправите это, присвоив элементам «размер», используя flex: number или flex-basis: 50px

. Я бы избежал атрибута ::marker, поскольку он получил ужасающую поддержку , и просто создал свой собственный с помощьюсчетчик css.

Вот пример:

ol {
  display:block;
  width: 30em;
  list-style: none;
  counter-reset: counterName;
}
li {
 padding-left: 2em;
 padding-bottom: 1em;
 border-bottom: 1px solid #ccc;
 margin-bottom: 1em;
 position: relative;
 counter-increment: counterName;
}
li:before {
  content:'#' counter(counterName);
  position: absolute;
  left:0;
  top:0;
}

.flex {
  display:flex;
  justify-content: space-between;
  flex-wrap:no-wrap;
}

.flex > * {
  flex: 1;
}
<ol>
    <li>
        <div class="flex">
            <div></div>
          <div>When an element without content is preceding, the ::marker of the list-item is located at the bottom.</div>
        </div>
    </li>
    <li>
        <div class="flex">
            <div>TITLE</div>
            <div>If there's content in the first element, then it goes as expected.</div>
        </div>
    </li>
    <li>
        <div class="flex">
            <div>It's also fine if there's only one child here.</div>
        </div>
    </li>
</ol>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...