Использование переполнения текста: многоточие с flexbox - PullRequest
0 голосов
/ 26 января 2019

Я создаю страницу корзины покупок и хочу перечислить изображение товара, название, цену и элемент формы, чтобы удалить его из корзины.

Я пытался использовать white-space: nowrap;, overflow: hidden; и text-overflow: ellipsis; вместе для элементов, которые я хочу обрезать, но я не могу понять, как правильно их отображать, особенно с img-container и name-price-container используя flexbox.

Вот мой шаблон Django:

<ul>
    {% for product in products %}
    <li class="row product">
        <div class="img-container">
            <a href="{% url 'gallery:product_page' %}?id={{ product.id }}">
                <img src="{{ product.image.url }}" alt="{{ product.name }}">
            </a>
        </div>
        <div class="name-price-container">
            <span>
                <a href="{% url 'gallery:product_page' %}?id={{ product.id }}">{{ product.name }} Loooooooooong Text</a>
            </span>
            <span>${{ product.price_per_unit }}</span>
        </div>
        <div class="btn-container">
            <form method="POST" action="{% url 'gallery:remove_cart' %}">
                {% csrf_token %}
                <input type="hidden" name="id" value="{{ product.id }}">
                <input type="submit" class="btn btn-light" value="Remove">
            </form>
        </div>
    </li>
    {% endfor %}
</ul>

... и соответствующий CSS:

.product .img-container {
  background-color: #343a40;
  border: 1px solid #343a40;
  box-sizing: unset;
  height: 128px;
  width: 128px;
  flex: 0 0 auto;
}
.product .img-container img {
  display: block;
  max-height: 128px;
  max-width: 128px;
  width: auto;
  height: auto;
}
.name-price-container {
  margin: 0 1rem;
  display: flex;
  flex: 1 0 auto;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}
.name-price-container a {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.btn-container {
  float: right;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.btn-container .btn {
  margin: 0;
}
@media all and (max-width: 768px) {
  body * {
    overflow: hidden;
  }
  .product .img-container {
    height: 64px;
    width: 64px;
  }
  .product .img-container img {
    max-width: 64px;
    max-height: 64px;
  }
}

... и рендеринг с шириной 470 пикселей: Изображение здесь

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

Любая помощь приветствуется.

Редактировать: Вот обновленный jsfiddle согласно комментарию Андрея.

Ответы [ 2 ]

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

Есть несколько изменений, которые необходимо внести, чтобы получить желаемое поведение.Прежде всего, вам нужно понять, что вы имеете дело с негативным космическим сценарием во flexbox.Именно тогда сумма длин содержимого превышает доступную родительскую длину.
В этом случае flexbox вычисляет разницу между ними и пытается равномерно распределить разницу между дочерними элементами, которые допускают flex-shrink, в соответствии с * 1003 каждого дочернего элемента.* фактор.

Так что вам нужно установить .name-price-container s flex-shrink на 1:

 .name-price-container {
    flex: 1 1 auto;
 }

Без него многоточие не произойдет, так как содержимое (ваше <a>) всегда будет расти столько, сколько им нужно, и поэтому будет устанавливать width, следовательно, flex-basis, .name-price-container (который в настоящее время не может уменьшиться).Следовательно, нет многоточия.


Вторая проблема связана с тем, что элементы <a> по умолчанию имеют display из inline.Чтобы заставить многоточие работать, вам нужен метод ограничения его ширины.Простейшим было бы дать ему display:block (потому что теперь родительский элемент уменьшен).В качестве альтернативы можно переместить эффект многоточия на span и задать этот интервал width: 100%.

Наконец, вы хотите предотвратить сокращение .btn-container и удалить его overflow.Дайте ему flex-shrink: 0 и удалите overflow: hidden из него.

Кстати, body * { overflow: hidden; } - это на самом деле , что вы хотите избежать, так как оно переопределяет значение по умолчанию overflow для каждого элемента на вашей странице,Есть много элементов, которые больше не будут работать, как ожидается, если вы измените это.Выпадающие списки, всплывающие подсказки, всплывающие окна и модалы и многие другие.

Вот ваш рабочий пример:

@import url('https://fonts.googleapis.com/css?family=Open+Sans');
* {
  font-family: 'Open Sans', Helvetica, Arial, sans-serif;
}
body {
  background-color: #e6ebf0;
}
ul {
  padding-left: 0;
}
ul li {
  list-style: none;
}
ul li img {
  width: 100%;
}
.img-container {
  background-color: #343a40;
  border: 1px solid #343a40;
	display: flex;
	flex: 1 0 auto;
	flex-direction: column;
  justify-content: center;
  align-items: center;
}
form {
  display: inline;
}
.btn-light {
  background-color: white;
  border: 1px solid #ced4da;
}
.row {
  margin: 0;
}
.product {
  display: flex;
}
.product,
.total {
  margin-top: 0.5rem;
  padding: 1rem;
  background-color: white;
  border: 1px solid #ced4da;
  border-radius: 4px;
}
.product .img-container {
  background-color: #343a40;
  border: 1px solid #343a40;
  box-sizing: unset;
  height: 128px;
  width: 128px;
  flex: 0 0 auto;
}
.product .img-container img {
  display: block;
  max-height: 128px;
  max-width: 128px;
  width: auto;
  height: auto;
}
.name-price-container {
  margin: 0 1rem;
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}
.name-price-container a {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.name-price-container a,
.name-price-container a:hover {
  color: #212529;
}
.btn-container {
  height: 130px;
  line-height: 130px;
  min-width: 0;
  white-space: nowrap;
}
.btn-container .btn {
  margin: 0;
  display: inline-block;
}
@media all and (max-width: 768px) {
  .product .img-container {
    height: 64px;
    width: 64px;
  }
  .product .img-container img {
    max-width: 64px;
    max-height: 64px;
  }
  .btn-container {
    height: 66px;
    line-height: 66px;
    flex-shrink: 0;
  }
}
<div class="container">
    <ul>
        
        <li class="row product">
            <div class="img-container">
                <a href="/gallery/product?id=21">
                    <img src="https://i.imgur.com/CyYN9a7.jpg" alt="Vials">
                </a>
            </div>
            <div class="name-price-container">
                <span>
                    <a href="/gallery/product?id=21">Vials Loooooooooong Text</a>
                </span>
                <span>$30.00</span>
            </div>
            <div class="btn-container">
                <form method="POST" action="/gallery/remove_cart">
                    <input type="hidden" name="csrfmiddlewaretoken" value="...">
                    <input type="hidden" name="id" value="21">
                    <input type="submit" class="btn btn-light" value="Remove">
                </form>
            </div>
        </li>
        
        <li class="row product">
            <div class="img-container">
                <a href="/gallery/product?id=22">
                    <img src="https://i.imgur.com/PoCaEjw.jpg" alt="Driftbird">
                </a>
            </div>
            <div class="name-price-container">
                <span>
                    <a href="/gallery/product?id=22">Driftbird Loooooooooong Text</a>
                </span>
                <span>$25.00</span>
            </div>
            <div class="btn-container">
                <form method="POST" action="/gallery/remove_cart">
                    <input type="hidden" name="csrfmiddlewaretoken" value="...">
                    <input type="hidden" name="id" value="22">
                    <input type="submit" class="btn btn-light" value="Remove">
                </form>
            </div>
        </li>
        
        <li class="row product">
            <div class="img-container">
                <a href="/gallery/product?id=19">
                    <img src="https://i.imgur.com/KxAyAyE.jpg" alt="Dragon">
                </a>
            </div>
            <div class="name-price-container">
                <span>
                    <a href="/gallery/product?id=19">Dragon Loooooooooong Text</a>
                </span>
                <span>$300.00</span>
            </div>
            <div class="btn-container">
                <form method="POST" action="/gallery/remove_cart">
                    <input type="hidden" name="csrfmiddlewaretoken" value="...">
                    <input type="hidden" name="id" value="19">
                    <input type="submit" class="btn btn-light" value="Remove">
                </form>
            </div>
        </li>
        
    </ul>
</div>

Обновлен скрипка здесь

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

Я знаю, что в вашем вопросе упоминается flexbox, но я бы использовал display: grid для этого случая. Сетка позволит вам более точно определить столбцы, сохранить пространство между каждым разделом содержимого в строке и обрезать это содержимое в области сетки.

Это также избавит вас от необходимости использовать float вместе с flexbox, что может иметь непредвиденные последствия. Поскольку содержимое четко определено в строках и столбцах любого размера, сетка является наиболее подходящим вариантом отображения того, что вы здесь делаете.

Это может выглядеть примерно так:

.product { //each .product container will contain 1 row with 3 columns
  display: grid;
  grid-gap: 1rem; //this adds a gap between the sections of your row
  grid-template: "image info button" 128px / 128px auto 128px; //i assumed your button is 128px wide
}

.product .img-container {
  background-color: #343a40;
  border: 1px solid #343a40;
  box-sizing: unset;
  grid-area: image; //this places the .img-container div within the "image" grid area defined above in grid-template
  height: 128px;
  width: 128px;
}
.product .img-container img {
  display: block;
  max-height: 128px;
  max-width: 128px;
  width: auto;
  height: auto;
}
.name-price-container {
  display: flex;
  flex-direction: column;
  grid-area: info; //this places the .img-container div within the "info" grid area
  justify-content: center;
  min-width: 0;
}
.name-price-container span {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.btn-container {
  display: flex;
  flex-direction: column;
  grid-area: button; //this places the .img-container div within the "button" grid area
  justify-content: center;
}
.btn-container .btn {
  margin: 0;
}
@media all and (max-width: 768px) {
  body * {
    overflow: hidden;
  }
  .product {
    grid-template: "image info button" 64px / 64px auto 128px;
  }
  .product .img-container {
    height: 64px;
    width: 64px;
  }
  .product .img-container img {
    max-width: 64px;
    max-height: 64px;
  }
}

См. этот кодовый блок для примера этого в действии.

Есть способ сделать то, что вы пытаетесь сделать с flexbox, но его не так просто поддерживать. Если вы потратите время, чтобы перевести это в сетку, у вас будет более надежный макет. Если вы попробуете этот код, вы обнаружите, что

Обратите внимание, что <= IE11 не полностью поддерживает grid, хотя вам может не потребоваться поддержка IE11 или ниже. Если вы это сделаете, есть специальные приемы для реализации макетов сетки с использованием префикса <code>-ms vendor. Здесь - отличная статья, в которой подробно описаны некоторые приемы, которые вы можете использовать (и модуль, который автоматически преобразует ваш CSS в IE11-совместимый).

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...