Я кодировал скрипт (с помощью пользователя здесь), который позволяет мне расширять выбранный div и заставлять другие div вести себя соответствующим образом, растягивая в равной степени, чтобы соответствовать оставшемуся пространству (кроме первого, ширина которого фиксирована).
И вот картина того, чего я хочу добиться:
Для этого я использую flex и переходы.
Это хорошо работает, но сценарий jQuery указывает значение растяжения «400%» (что отлично подходит для тестирования).
Теперь я хотел бы, чтобы выбранный div расширялся / сжимался, чтобы точно соответствовать содержимому вместо фиксированного значения «400%».
Я понятия не имею, как я мог это сделать.
Является ли это возможным ?
Я попытался клонировать div, подогнать его к содержимому, получить его значение и затем использовать это значение для перехода, НО это означает, что у меня есть начальная ширина в процентах, но целевое значение в пикселях. Это не работает
И если я преобразую значение пикселя в процентах, то результат по какой-то причине не совсем соответствует содержанию.
Во всех случаях это кажется довольно сложным способом добиться того, чего я хочу в любом случае.
Нет ли какого-либо свойства flex, которое можно было бы переместить, чтобы соответствовать содержимому выбранного div?
Вот код ( отредактированный / упрощенный, так как для лучшего чтения ):
var expanded = '';
$(document).on("click", ".div:not(:first-child)", function(e) {
var thisInd =$(this).index();
if(expanded != thisInd) {
//fit clicked fluid div to its content and reset the other fluid divs
$(this).css("width", "400%");
$('.div').not(':first').not(this).css("width", "100%");
expanded = thisInd;
} else {
//reset all fluid divs
$('.div').not(':first').css("width", "100%");
expanded = '';
}
});
.wrapper {
overflow: hidden;
width: 100%;
margin-top: 20px;
border: 1px solid black;
display: flex;
justify-content: flex-start;
}
.div {
overflow: hidden;
white-space: nowrap;
border-right: 1px solid black;
text-align:center;
}
.div:first-child {
min-width: 36px;
background: #999;
}
.div:not(:first-child) {
width: 100%;
transition: width 1s;
}
.div:not(:first-child) span {
background: #ddd;
}
.div:last-child {
border-right: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Click on the div you want to fit/reset (except the first div)
<div class="wrapper">
<div class="div"><span>Fixed</span></div>
<div class="div"><span>Fluid (long long long long long text)</span></div>
<div class="div"><span>Fluid</span></div>
<div class="div"><span>Fluid</span></div>
</div>
Вот jsfiddle:
https://jsfiddle.net/zajsLrxp/1/
РЕДАКТИРОВАТЬ: Вот мое рабочее решение с помощью всех вас (размеры обновляются при изменении размера окна + количество делений и динамически рассчитывается ширина первого столбца):
var tableWidth;
var expanded = '';
var fixedDivWidth = 0;
var flexPercentage = 100/($('.column').length-1);
$(document).ready(function() {
// Set width of first fixed column
$('.column:first-child .cell .fit').each(function() {
var tempFixedDivWidth = $(this)[0].getBoundingClientRect().width;
if( tempFixedDivWidth > fixedDivWidth ){fixedDivWidth = tempFixedDivWidth;}
});
$('.column:first-child' ).css('min-width',fixedDivWidth+'px')
//Reset all fluid columns
$('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')
})
$(window).resize( function() {
//Reset all fluid columns
$('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')
expanded = '';
})
$(document).on("click", ".column:not(:first-child)", function(e) {
var thisInd =$(this).index();
// if first click on a fluid column
if(expanded != thisInd)
{
var fitDivWidth=0;
// Set width of selected fluid column
$(this).find('.fit').each(function() {
var c = $(this)[0].getBoundingClientRect().width;
if( c > fitDivWidth ){fitDivWidth = c;}
});
tableWidth = $('.mainTable')[0].getBoundingClientRect().width;
$(this).css('flex','0 0 '+ 100/(tableWidth/fitDivWidth) +'%')
// Use remaining space equally for all other fluid column
$('.column').not(':first').not(this).css('flex','1 1 '+flexPercentage+'%')
expanded = thisInd;
}
// if second click on a fluid column
else
{
//Reset all fluid columns
$('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')
expanded = '';
}
});
body{
font-family: 'Arial';
font-size: 12px;
padding: 20px;
}
.mainTable {
overflow: hidden;
width: 100%;
border: 1px solid black;
display: flex;
margin-top : 20px;
}
.cell{
height: 32px;
border-top: 1px solid black;
white-space: nowrap;
}
.cell:first-child{
background: #ccc;
border-top: none;
}
.column {
border-right: 1px solid black;
transition: flex 0.4s;
overflow: hidden;
line-height: 32px;
text-align: center;
}
.column:first-child {
background: #ccc;
}
.column:last-child {
border-right: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="text">Click on the header div you want to fit/reset (except the first one which is fixed)</span>
<div class="mainTable">
<div class="column">
<div class="cell"><span class="fit">Propriété</span></div>
<div class="cell"><span class="fit">Artisan 45</span></div>
<div class="cell"><span class="fit">Waterloo 528</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Adresse</span></div>
<div class="cell"><span class="fit">Rue du puit n° 45 (E2)</span></div>
<div class="cell"><span class="fit">Chaussée de Waterloo n° 528 (E1)</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Commune</span></div>
<div class="cell"><span class="fit">Ixelles</span></div>
<div class="cell"><span class="fit">Watermael-Boitsfort</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Ville</span></div>
<div class="cell"><span class="fit">Marche-en-Famenne</span></div>
<div class="cell"><span class="fit">Bruxelles</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Surface</span></div>
<div class="cell"><span class="fit">120 m<sup>2</sup></span></div>
<div class="cell"><span class="fit">350 m<sup>2</sup></span></div>
</div>
</div>
И вот полный пример на работе (стили + отступы + больше данных):
https://jsfiddle.net/zrqLowx0/2/
Спасибо вам всем !
источник
Ответы:
Это можно решить используя
max-width
иcalc()
.Во- первых, заменить
width: 100%
сflex: 1
для дивы в CSS, таким образом , они будут расти, что лучше в этом случае. Кроме того, используйте переход дляmax-width
.Теперь мы должны сохранить некоторые соответствующие значения:
divsLength
переменные) - 3 в этом случае.extraSpace
переменная) - в этом случае 39px.С этими двумя переменными мы можем установить значение по умолчанию
max-width
(defaultMaxWidth
переменную) для всех элементов div, а также использовать их позже. Вот почему они хранятся по всему миру.defaultMaxWidth
Этоcalc((100% - extraSpace)/divsLength)
.Теперь давайте введем функцию щелчка:
Чтобы расширить div, ширина целевого текста будет сохранена в переменной с именем,
textWidth
и она будет применена к div, какmax-width.
он использует.getBoundingClientRect().width
(так как он возвращает значение с плавающей запятой).Для остальных элементов div он создается
calc()
для того,max-width
что будет применяться к ним.Это:
calc(100% - textWidth - extraScape)/(divsLength - 1)
.Расчетный результат - это ширина, которой должен быть каждый оставшийся div.
При щелчке по расширенному элементу div, то есть для возврата к нормальному состоянию, значение по умолчанию
max-width
снова применяется ко всем.div
элементам.Этот подход ведет себя динамически и должен работать на любом разрешении.
Единственное значение, которое вам нужно для жесткого кода - это
extraSpace
переменная.источник
Вам нужно разобраться с функциями width или calc. У Flexbox было бы решение.
Чтобы сделать все div одинаковыми (не первыми) мы используем
flex: 1 1 auto
.Определите гибкие правила для вашего обычного div и выбранного div.
transition: flex 1s;
твой друг. Для выбранного нам не нужно Flex Grow, поэтому мы используемflex: 0 0 auto
;Добавляйте выбранный класс каждый раз, когда пользователь нажимает div. Вы также можете использовать переключатель для второго щелчка, чтобы сохранить выбранные элементы на карте и показать несколько выбранных элементов (конечно, не с этим примером кода).
https://jsfiddle.net/f3ao8xcj/
источник
Flex transition: Stretch (or shrink) to fit content
название вашего вопроса, и этот ответ является простым примером того, как это сделать. Это ваша ответственность, чтобы найти решение для вашего случая.После нескольких пробных версий это, кажется, мое самое короткое и простое решение.
Все, что по сути нужно сделать, - это заставить Flexbox растягивать
<div>
элементы до их пределов по умолчанию, но при<span>
нажатии ограничить растяжение<div>
до<span>
ширины ...псевдокод:
when <span> clicked and already toggled then <div> max-width = 100%, reset <span> toggle state
otherwise <div> max-width = <span> width, set <span> toggle state
Я разбил CSS на разделы «соответствующий механизм» и «только для глаз» для удобства чтения (и повторного использования кода).
Код сильно комментируется, поэтому здесь не так много текста ...
Причуды Почему-то есть дополнительная задержка
transition
при переключенииdiv
сmax-width: 100%
наmax-width = span width
. Я проверил это поведение в Chrome, Edge, IE11 и Firefox (все W10), и все, кажется, имеют эту причуду. Либо происходит какой-то внутренний браузер, либоtransition
время используется дважды («по ощущениям»). Наоборот, как ни странно, никаких дополнительных задержек нет.Тем не менее, при коротком времени перехода (например, 150 мс, как я сейчас использую), эта дополнительная задержка не заметна. (Хороший для другого ТАК вопрос ...)
Показать фрагмент кода
ОБНОВИТЬ
Новая версия, которая сбрасывает все остальные
<div>
. Я действительно ненавижу скачок, но это происходит из-за растяжения Flexbox и егоtransition
ценности. Безtransition
скачков видно. Вы должны попробовать то, что работает для вас.Я только добавил
document.querySelectorAll()
к коду JavaScript.Показать фрагмент кода
источник