На первый взгляд, ваша проблема выглядит более сложной, чем на самом деле. Хитрость заключается в том, чтобы игнорировать вашу ссылку на Django, такие как линии и цвета, и упростить ваш вопрос до:
Учитывая фиксированную ширину родителя, равномерно распределите дочерние элементы в родительском элементе с учетом их ширины.
- Мы получаем
parent.width
из базы данных, DjangoParentSizeValue
- Также из базы данных мы знаем ширину отображаемых элементов:
DjangoHighValue - DjangoLowValue = child.width
Механизм Flexbox уже предоставляет способ распространения дочерних элементов, так почему бы не использовать это:
Parent : display: flex
=> по умолчанию - строка flexbox без переноса, состоящая из 1: N столбцов.
Ребенок : flex-grow: 'javascript calculated'=> high - low = value
. Правильно, игнорируйте значение CSS width
, просто установите значение CSS flex-grow
.
A flex-grow
value> 0 означает, что элемент может расти внутри родительского элемента. Обычно это 0 или 1 (без увеличения = по умолчанию / увеличения), но оно может иметь любое значение. Предоставляя дочерним элементам значение flex-grow
, рассчитанное по данным базы данных Django (вместо 0/1), механизм Flexbox будет равномерно распределять их внутри родительского элемента. Как раз то, что нам нужно !!
И это действительно так, все остальное - eyecandy.
Теперь вам нужно только решить, что делать со значением родительской ширины, полученным из базы данных: 100%, x раз ширина области просмотра, x раз ширина экрана смартфона и т. Д.
Вам все равно придется установить ограничение на ширину родительского элемента, в любом случае, пользователи ненавидят много раз прокручивать или пролистывать влево / вправо (я знаю, что знаю!).
Eyecandy: все, кроме последнего дочернего элемента, получают margin-right
(любое значение, которое вам требуется).
Для линий между ними я просто использую изображение SVG, которое рисует линию на родительском фоне.
В примере псевдо-javascript показан простой цикл for, присваивающий значения flex-grow
дочерним элементам.
Код кажется много, но 99% это просто пример.
Наконец: отметьте LeaderLine , если вам нужно, чтобы ваши строки были кликабельными и имели некоторые функциональные возможности. Я только недавно обнаружил эту библиотеку (с исходным кодом Github), и она кажется очень забавной ...
/*
Psuedo/None working example Javascript code
*/
function setFlexGrowValues() {
// Get a list of all FBL parents
var parentList = document.querySelectorAll('.parent');
var childList,x,y;
// Traverse parent list
for (x = 0; x < parentList.length; x++) {
// Get all the 'button' child elements inside the parent
childList = parentList[x].querySelectorAll('button');
// Traverse the parent.button.list
for (y = 0; y < childList.length; y++) {
// Calculate and assign the the width found in the Django Database
childList[y].style.flexGrow = DjangoHighValue - DjangoLowValue;
}
}
};
/*
- A Flexbox parent container is a none wrapping row (of 1:N columns) by default.
- In this case FBL container must have some (min-/max-) width set so the FBL mechanism
can use that width to properly distribute the FBL child elements with the flex-grow value.
- Width can be 100% (like here), but essentially any value will do (fixed or relative units).
The FBL mechanism will use the flex-grow value as a 'ratio' for distributing the child elements.
- Combined with the 'flex-grow' attribute of the child elements, the only relevant CSS to make
things work is the below line.
Any other styling like a line, border, spacing, colors is arbitrary and yours to decide upon.
*/
.parent { display: flex; width: 100% }
/* using some simple elements spacing => eyecandy */
.parent>button { margin-right: 1rem }
/* No right margin for the last child in line => eyecandy */
.parent>:last-child { margin-right: 0 }
/*
No need to use calculation for some line to draw, just use an inline svg to do the job
and draw a line as a background image from parent (0,50%) upto parent (100%,50%) => eyecandy
*/
.parent { background-image: url('data:image/svg+xml, \
<svg xmlns="http://www.w3.org/2000/svg"> \
<line x1="0" x2="100%" y1="50%" y2="50%" height="1" stroke="black" /> \
</svg>');
}
/* irrelevant, again: eyecandy */
button { height: 1.5rem; border: 1px solid LightGrey; cursor: pointer }
<div class="parent"><!-- 'style' created by CSS or JS. Here as example only! -->
<button style="flex-grow: 4000; background-color: PaleTurquoise">1</button>
<button style="flex-grow: 1000; background-color: Chartreuse" >2</button>
<button style="flex-grow: 500; background-color: LemonChiffon" >3</button>
<button style="flex-grow: 1350; background-color: Cornsilk" >4</button>
<button style="flex-grow: 750; background-color: GreenYellow" >5</button>
<button style="flex-grow: 550; background-color: DarkSeaGreen" >6</button>
</div>
<div class="parent">
<button style="flex-grow: 1000; background-color: Chartreuse" >1</button>
<button style="flex-grow: 750; background-color: GreenYellow" >2</button>
<button style="flex-grow: 1350; background-color: Cornsilk" >3</button>
<button style="flex-grow: 500; background-color: LemonChiffon" >4</button>
<button style="flex-grow: 550; background-color: DarkSeaGreen" >5</button>
<button style="flex-grow: 4000; background-color: PaleTurquoise">6</button>
</div>
<div class="parent">
<button style="flex-grow: 550; background-color: DarkSeaGreen" >1</button>
<button style="flex-grow: 4000; background-color: PaleTurquoise">2</button>
<button style="flex-grow: 1000; background-color: Chartreuse" >3</button>
<button style="flex-grow: 500; background-color: LemonChiffon" >4</button>
<button style="flex-grow: 750; background-color: GreenYellow" >5</button>
<button style="flex-grow: 1350; background-color: Cornsilk" >6</button>
</div>