CSS floats: как сохранить float рядом с текстом, к которому он принадлежит?

У меня есть процедура, состоящая из шагов. Некоторые шаги сопровождаются изображением.

    <p class="imagefloatright"><img src="step 1.png"/></p>
    <ol>
        <li>
          <p>Step 1</p>
          <p class="imagefloatright"><img src="step 2.png"/></p>
        </li>
        <li>
          <p>Step 2</p>
          <p>Step 3</p>
        </li>
    </ol>

и мой CSS:

p.imagefloatright img {
    float: right;
    clear: both;
}

Это выход по умолчанию. Изображения не остаются с шагами, к которым они принадлежат, текст для шага 2 помещается рядом с изображением 1:

enter image description here

Я хочу, чтобы изображение, относящееся к шагу 2, было выровнено по вертикали с шагом 2:

enter image description here

Раньше я добился желаемого результата в XSL-FO, вставив блок полноразмерной высоты с высотой = 0 перед каждым плавающим изображением.

Могу ли я достичь желаемого макета с помощью команд CSS? Или мне нужно вставить блок в HTML, прежде чем применять CSS к HTML?

Ответ 1

Вы должны использовать свойство clear не для элемента p, а создать другой элемент в том месте, где вы хотите остановить float.

p.imagefloatright img {
    float: right;
}

.clear {
    clear:both;
}
<p class="imagefloatright"><img src="http://via.placeholder.com/80x80"/></p>
<p>Step 1</p>
<div class="clear"></div>
<p class="imagefloatright"><img src="http://via.placeholder.com/80x80"/></p>
<p>Step 2</p>
<div class="clear"></div>

Ответ 2

Если на каждом шаге с изображением будет только одно изображение, и изображение не будет использоваться более чем на один шаг, вы можете написать селектор, чтобы сделать следующий шаг, чтобы очистить каждое плавающее изображение, но оно очень жесткое:

p.imagefloatright img {
  clear: both;
  float: right;
}

p.imagefloatright + p:not(.imagefloatright) + p {
  clear: both;
}
<p class="imagefloatright"><img src="https://placehold.it/100x100"/></p>
<p>Step 1</p>
<p class="imagefloatright"><img src="https://placehold.it/100x100"/></p>
<p class="imagefloatright"><img src="https://placehold.it/100x100"/></p>
<p>Step 2</p>
<p>Step 3</p>

Ответ 3

Вот простой способ с flexbox:

ol {
  list-style: none;
  padding:0;
  margin:0;
}

li {
  display: flex;
  /*for illustration*/
  border:1px solid;
  padding:5px;
}

img {
  margin-left: auto;
}
<ol>
  <li>
    Step 1
    <img src="https://placehold.it/100x100">
  </li>
  <li>
    Step 2
  </li>
  <li>
    Step 3
  </li>
  <li>
    Step 4
    <img src="https://placehold.it/100x100">
  </li>
</ol>

Ответ 4

Очистить float, который содержит динамический контент, т.е. изображение может иметь динамическую высоту, вам нужно очистить сам родительский элемент.

.imagefloatright {
  clear: both;
}
.imagefloatright img {
  float: right;
}

Это означает, что вам нужно использовать clear на элементе, который содержит плавающие элементы.


Для краткости я бы переименовал его так:

.clearfix {
  clear: both;
}
.float-right {
  float: right;
}

HTML

<p class="clearfix"><img class="float-right" src="step 1.png"/></p>
<ol>
    <li>
      <p>Step 1</p>
      <p class="clearfix"><img class="float-right" src="step 2.png"/></p>
    </li>
    <li>
      <p>Step 2</p>
      <p>Step 3</p>
    </li>
</ol>

Вот демо.

Ответ 5

Решение 1: Использование Flex

Я бы рекомендовал использовать flex и justify-content: space-between единственным недостатком для его использования было бы, если вы поддерживаете более старые браузеры, такие как IE10-, тогда вы можете проверить https://caniuse.com/#search=flex для получения дополнительной информации,

Что касается space-between простыми, как в соответствии с MDN

Элементы равномерно распределены внутри контейнера выравнивания вдоль основной оси. Расстояние между каждой парой смежных элементов одинаково. Первый элемент заподлицо с краем основного запуска, а последний элемент заподлицо с краем основного конца.

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

Лично я бы нашел, что использование flex является самым удобным и одним из самых чистых способов "позиционирования" и "компоновки" различных элементов на странице.

Вы можете найти код ниже и рабочую скрипку здесь

HTML

<ol class="step-list">
  <li class="step">
    <p>Step 1</p>
    <img src="https://placehold.it/150x150?text=Step1" alt="">
  </li>
  <li class="step">
    <p>Step 2</p>
  </li>
  <li class="step">
    <p>Step 3</p>
  </li>
  <li class="step">
    <p>Step 4</p>
    <img src="https://placehold.it/150x150?text=Step4" alt="">
  </li>
</ol>

CSS

.step-list {
  list-style: none;
}

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

Решение 2. Использование Float

Вы также можете использовать float но в этом случае вам нужно очистить p вместо img и поплавать.

Поскольку весь элемент содержащихся элементов clearfix важно добавить clearfix в тег li чтобы он не сворачивался, и вы ничего не можете найти здесь.

Таким образом, ваш код понравится, и вы можете найти рабочую скрипку здесь

HTML

<ol class="step-list">
  <li class="step">
    <p>Step 1</p>
    <img src="http://placehold.it/150x150?text=Step1" alt="">
  </li>
  <li class="step">
    <p>Step 2</p>
  </li>
  <li class="step">
    <p>Step 3</p>
  </li>
  <li class="step">
    <p>Step 4</p>
    <img src="http://placehold.it/150x150?text=Step4" alt="">
  </li>
</ol>

CSS

.step-list {
  list-style: none;
}

.step img {
  float: right;
}

.step p {
  float: left;
}

/*This is what is called a clearfix solution, for the floating problem*/
.step::after {
  content: "";
  display: block; 
  clear: both;
}

Не стесняйтесь задавать мне больше вопросов, если что-то неясно.

Ответ 6

clearfix должно помочь. :

.clearfix:after {
  display: block;
  content: "";
  clear: both;
}

И html:

<p class="imagefloatright"><img src="http://via.placeholder.com/80x80"/></p>
<p class="clearfix">Step 1</p>
<p class="imagefloatright"><img src="http://via.placeholder.com/80x80"/></p>
<p class="clearfix">Step 2</p>
<p>Step 3</p>

Ответ 7

Почему не с псевдоэлементом?

p, .imagefloatright img { margin: 0 0 .25em; }

.imagefloatright img {
  float: right;
}

.imagefloatright::before {
  clear: both;
  content: '';
  display: block;
}
<p class="imagefloatright"><img src="http://via.placeholder.com/80x80"/></p>
<p>Step 1</p>
<p class="imagefloatright"><img src="http://via.placeholder.com/80x80"/></p>
<p>Step 2</p>
<p>Step 3</p>
<p class="imagefloatright"><img src="http://via.placeholder.com/80x80"/></p>
<p>Step 4</p>
<p>Step 5</p>

Ответ 8

Вы можете использовать это

 <p>
    <span class="left">1</span>
       <img class="right"  src="http://via.placeholder.com/90x90" alt="">
  </p>

   <p>
    <span class="left">2</span>
       <img class="right"  src="http://via.placeholder.com/90x90" alt="">
  </p>

p{
  display:inline-block;
    margin-bottom:5px;
    width:100%;
}
p .left{
  float:left;
  margin-bottom:55px;
}
p .right{
 float:right;
}

https://jsfiddle.net/jlbarcelona/vcmdo7uy/106/

Ответ 9

Это очень легко сделать. Когда вы используете свойство css float, вы должны использовать переполнение с его родительским элементом. В вашей ситуации:

p.imagefloatright{
   overflow: auto;
}

должен решить проблему. Узнайте больше о https://www.w3schools.com/css/css_float.asp

Ответ 10

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

ol {
  padding: 0;
}

li {
  padding: 10px;
  list-style: none;
  background: #eee;
  margin: 10px 0;
  width: auto;
}

li:after {
  content: '';
  display: table;
  clear: both;
}

li > p {
  width: 25%;
  float: left;
}

p {
  margin: 0;
}
<p><img src="http://fpoimg.com/300x300"/></p>
<ol>
  <li>
    <p>Step 1</p>
    <p><img src="http://fpoimg.com/300x300?text=Step1"/></p>
  </li>
  <li>
    <p>Step 2</p>
    <p>Step 3</p>
  </li>
</ol>