Класс таблицы для таблиц, которые при слишком широком распределении всех своих ячеек в строки
Я пытаюсь выяснить, какой HTML/CSS мне нужно, чтобы получить определенное нарушение поведения в зависимости от того, сколько места доступно. В принципе, я хочу, чтобы длинная строка текста автоматически ломалась в определенных местах, и все в одном), когда для нее больше нет места.
Пример 1:
Пример 2: Это то же самое, что и в предыдущем примере, но это показывает, что я хотел бы также использовать его вложенным образом:
-
Достаточно горизонтального пространства для всей строки текста:
![введите описание изображения здесь]()
-
Просто недостаточно горизонтального пространства для всей строки, поэтому каждая ячейка переходит в свою собственную строку
![введите описание изображения здесь]()
-
Недостаточно горизонтального пространства для второй ячейки
![введите описание изображения здесь]()
Я ищу решение, которое использует только HTML и CSS (или просто использует JavaScript очень легко), поскольку мой предполагаемый прецедент - это очень сильно использовать это в автоматически созданных страницах документации HTML.
Я встречал такие примеры, как эти, но я не уверен, что вижу, как сделать эту работу для подэлементов (и как сделайте эту работу без назначения фиксированного размера каждой ячейке - я хочу, чтобы размер ячейки определялся ее содержимым).
Редактирование Clarfiying
Просто уделяя особое внимание важной части вопроса, который был упущен. Я никогда не хочу оказаться в состоянии, когда на одной строке есть два элемента, а третий - на следующей строке. Три элемента должны идти прямо от того, чтобы быть на одной линии для всех на отдельных строках.
Ответы
Ответ 1
Как я уже говорил в комментариях, то, что ищет OP, не может быть достигнуто без использования Javascript, поэтому вот что я придумал.
Первоначально у нас есть нормальная структура таблицы, мы вычисляем каждую ширину таблицы и применяем атрибут data-width
для каждой таблицы - родительский или вложенный.
При изменении размера, как только каждая таблица будет длиннее ширины окна, она изменит отображение содержимого с table-cell
на block
, тем самым уложив все дочерние элементы.
Как только ширина окна расширяется, он сравнивается с каждым атрибутом таблицы data-width
, и когда он подходит, он расширяется.
edit: Я подумал, что по некоторым причинам он не будет работать в некоторых случаях, но он действительно работает, поэтому я удаляю раздувание!
HTML:
<div class="table">
<div class="cell">
Content 1
</div>
<div class="cell">
<div class="table">
<div class="cell">
Content 1
</div>
<div class="cell">
Cont
</div>
<div class="cell">
Content 3
</div>
</div>
</div>
<div class="cell">
Content 3Content 3Content 3
</div>
</div>
CSS
.table {
display: table;
border: 1px solid #e4e5e7;
white-space: nowrap;
}
.cell {
display: table-cell;
vertical-align: middle;
padding: 10px;
border: 1px solid #e4e5e7;
}
.cell .table {
margin-bottom: -2px;
}
.table.wrap {
white-space: normal;
}
.table.wrap > .cell {
display: block;
}
JavaScript:
$('.table').each(function(i) {
tw = 0;
$(this).children('.cell').each(function() {
tw += $(this).outerWidth(true);
});
$(this).attr('data-width', tw);
});
$(window).on('load resize', function() {
w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
$('.table').each(function(i) {
if ($(this).width() >= w) {
$(this).addClass('wrap');
} else if (w >= $(this).attr('data-width')) {
$(this).removeClass('wrap');
}
});
}).resize();
И здесь работает fiddle
Ответ 2
Другой вариант с чистым JS
window.addEventListener('load', collapse);
window.addEventListener('resize', collapse);
function collapse() {
var parents = document.querySelectorAll('.parent');
var children;
var width;
for (var i = 0; i < parents.length; i++) {
parents[i].classList.remove('collapsed');
width = 0;
children = parents[i].children;
for (var j = 0; j < children.length; j++) {
width += children[j].offsetWidth;
}
if (width > parents[i].offsetWidth) {
parents[i].classList.add('collapsed');
}
}
}
.parent,
.child {
border: 1px solid gray;
margin: 5px;
padding: 5px;
}
.parent {
display: flex;
flex-wrap: wrap;
}
.collapsed {
display: block;
}
.child {
flex-grow: 1;
}
<div class="parent">
<div class="child">Some thing one</div>
<div class="parent child">
<div class="child">Some inner</div>
<div class="child">long thing</div>
<div class="child">two</div>
</div>
<div class="child">Thing three</div>
</div>
Ответ 3
Один подход заключается в использовании запросов @media
для чередования между
display: block
и
display: inline-block
Рабочий пример:
.long-row {
display: inline-block;
width: 200px;
padding-left: 4px;
font-size: 16px;
line-height: 32px;
border: 1px solid rgb(0, 0, 0);
}
@media only screen and (min-width: 801px) {
.long-row {
display: inline-block;
float: left;
}
}
@media only screen and (max-width: 800px) {
.long-row {
display: block;
border-top: none;
}
div:first-of-type.long-row {
border-top: 1px solid rgb(0, 0, 0);
}
}
@media only screen and (max-width: 600px) {
.long-row {
}
.short-row {
display: block;
margin-left: -4px;
padding-left: 4px;
border-bottom: 1px solid rgb(0, 0, 0);
}
span:last-of-type.short-row {
border-bottom: none;
}
}
<div class="long-row">Some thing one</div>
<div class="long-row">
<span class="short-row">Some inner</span>
<span class="short-row">long thing</span>
<span class="short-row">two</span>
</div>
<div class="long-row">Thing three</div>
Ответ 4
Прежде чем перейти к script, есть пары заметок, которые следует учитывать:
В моем фактическом состоянии, о котором я знаю, это невозможно сделать, используя только CSS. Итак, вопрос в том, как это сделать, используя чистый JavaScript с лучшей производительностью? И я придумал некоторые рекомендации:
В дополнение к этому он может быть вложен на любой уровень
Идея:
script принимает все элементы, заставляет их в одну строку и видит, недостаточно ли места, чтобы они отображались друг на друга, в противном случае они оставались в одной строке.
Он делает это каждый раз при загрузке разметки документа и при изменении размера окна.
https://jsfiddle.net/nasdao/qzdtr9ym/
Ура!
Ответ 5
Как я упоминал в своем комментарии, вы можете использовать flexbox, вот демонстрация того, как вы хотели. Надеюсь, это поможет.
.flex-container {
display: flex;
align-items: center;
flex-direction: row;
flex-wrap: wrap;
flex-flow: row wrap;
align-content: flex-end;
}
.flex-item {
background: gray;
color: white;
margin: 2px;
height: 80px;
text-align: center;
font-size: 30px;
border:3px solid black;
}
<div>
<div class="flex-container">
<div class="flex-item">Something One</div>
<div class="flex-container" style="border:2px solid black">
<div class="flex-item">Something 2</div>
<div class="flex-item">Something random3</div>
<div class="flex-item">Some 4</div>
</div>
<div class="flex-item">Something Five</div>
</div>
Ответ 6
Вы можете сделать это с помощью дисплея: flex;
Например:
.horz_cont {
display: flex;
align-items: center;
flex-direction: row;
flex-wrap: wrap;
flex-flow: row wrap;
align-content: flex-end;
border: 1px solid #000;
padding: 4px;
}
.horz_cont .horz_cont {
border: none;
padding: 0;
}
.item {
display: flex;
align-items: center;
justify-content: center;
margin: 4px;
padding: 4px;
height: 50px;
font-size: 34px;
font-weight: bold;
border: 1px solid #000;
}
<div class="horz_cont">
<div class="item">Some thing one</div>
<div class="horz_cont">
<div class="item">Some inner</div>
<div class="item">long thing</div>
<div class="item">two</div>
</div>
<div class="horz_cont">
<div class="item">Thing three</div>
</div>
</div>
Ответ 7
Вы можете попробовать использовать медиа-запросы на размерах экрана, так что, когда внутренний контент среднего flexbox превышает свой контейнер, вы можете написать CSS, который применим только к этому сценарию.
Важно также добавить тег viewport к заголовку html:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Откройте пример в полноэкранном режиме и измените размер окна просмотра браузера, чтобы увидеть, как элементы появляются вокруг.
Надеюсь, это вам поможет.
Ура!
.flex-container {
display: flex;
align-items: center;
flex-direction: row;
flex-wrap: wrap;
flex-flow: row wrap;
align-content: flex-end;
}
.flex-item, .inner-flex-item {
background: white;
color: black;
padding: 5px;
margin: 2px;
height: 100px;
text-align: center;
line-height: 100px;
font-size: 50px;
border:3px solid black;
}
@media screen and (max-width: 1180px) {
.flex-item {
width: 80%;
}
@media screen and (max-width: 640px) {
.inner-flex-item {
width: 80%;
}
<div>
<div class="flex-container">
<div class="flex-item">Something One</div>
<div class="flex-container" style="border:2px solid black">
<div class="inner-flex-item">Some inner</div>
<div class="inner-flex-item">long thing</div>
<div class="inner-flex-item">two</div>
</div>
<div class="flex-item">Thing three</div>
</div>
Ответ 8
Я не знаю, как это сделать при каждом размере экрана в чистом css. Мне нужно немного javascript (проще с jquery)
- Эти элементы являются встроенными блоками.
- Для каждой группы элементов сиблинга проверьте, совпадает ли верхняя позиция последнего ребенка с верхней позицией первого ребенка (если это так, они находятся в одной строке).
- Если не та же самая верхняя позиция, добавьте класс, чтобы сделать их блоки снова (несмотря на встроенные блоки).
Хорошо работает с n-вложенными уровнями, и это достаточно легкий javascript. (плюс никаких запросов к мультимедиа, никакого количества элементов на уровне, без циклов с "попыткой подгонки", возможно, самой широкой поддержки браузера...)
$(function() {
$('div.line:first-child ~ div.line:last-child').each(
function(){
if( $(this).position().top != $(this).siblings(":first-child").position().top ){
$(this).parent().addClass("breaks")
}
}
);
});
div{outline:1px solid red;}
.line{display:inline-block;}
.breaks > .line{display:block;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="line">Some thing one</div>
<div class="line">
<div class="line">Some inner</div>
<div class="line">longest thing</div>
<div class="line">two</div>
</div>
<div class="line">this is long Thing three</div>
</div>