So this one is a little bit hard to explain, but I'll try it:
I've got a div with the class .boxes. It's the wrapper of some looped elements. The looped elements have the class .box. Within this element, there are two more elements. One is the header with the class .box-header and one is the content with the class .box-content. I can open and close this elements with a click on it, so if it's closed, I just see the .box-header and if it's opened, I can see also the .box-content.
Here is a screenshot, which shows you how this looks like (grey container .boxes with the elements .box within in different states closed/opened):
I've got such lists in different components, so more than one time. The structure is mostly the same. So a example template of this looks like this:
<!--wrapper boxes-->
<div class="boxes">
<!--looped element box-->
<div class="box boxFor{{::box.id}}" ng-repeat="box in boxes" ng-class="{fill-container: boxes.length == 1}">
<!--box header-->
<div class="box-header" ng-click="box.open = !box.open">
{{::box.name}}
</div>
<!--box content-->
<div class="box-content" ng-if="box.open">
<!--some content-->
</div>
</div>
</div>
Here is a example style of the classes:
.boxes {
display: flex;
flex: 1 1 auto;
flex-direction: column;
overflow: auto;
.box {
display: flex;
flex-direction: column;
flex: 0 0 auto;
margin-bottom: 5px;
}
.box-header {
display: flex;
flex-direction: row;
justify-content: flex-start;
min-height: 30px;
line-height: 20px;
font-size: 16px;
padding: 5px;
}
.box-content{
padding: 5px;
display: flex;
flex-direction: column;
flex: 1 1 auto;
margin-top: 5px;
}
.fill-container {
flex: 1 1 auto;
}
}
Now one requirement was, that everytime I open a box, it should take 50% of the height from his wrapper. So .box should have a height: 50%; of .boxes. This mean, I can see in maximum 2 opened boxes in the same time. When I open a third etc., it also should take the same height of 50% from .boxes, but I have to scroll to see it. If I just have one box, it should fill the whole container when I open it, this is solved with the ng-class="{fill-container: boxes.length == 1}" and works fine. I also implemented a function, which calculates and sets the 50% correctly to .box and it's also correct on the screen like in my screenshots. I did it like this:
In the ng-click of my .box-header, I call a function named setBoxHeight() in my controller, which calculates and sets me the correct height:
<div class="box-header" ng-click="box.open = !box.open; ctrl.setBoxHeight()">
{{::box.name}}
</div>
The function looks like this:
setBoxHeight() {
if (this.boxes.length > 1) {
let boxHeaderHeight = $('.box-header').outerHeight();
let halfHeight = Math.round($('.boxes').outerHeight() / 2);
this.boxes.forEach((box: any) => {
let element = $('.boxFor' + box.id);
if (box.open) {
element.height(halfHeight);
} else {
element.height(boxHeaderHeight);
}
});
}
}
If you compare my template and this function, it should be clear what happens. This works also fine. The problem is, that I have to implement it in every list I have on different controllers for different components. I would like to unify it and run it centrally for all lists. It should be a clean solution. I tried to build a external component and pass throught the boxes and their class names with some bindings and call once the function, something like this:
<my-component items="ctrl.boxes" header-class="'.box-header'" wrapper-class="'.boxes'"></my-component>
I'm pretty sure, there is a cleaner way to do this. I hope my question is clear enough. Any ideas?
You could go for an all-CSS solution, and use the flex-basis property (see documentation). Basically, it sets the default size of flexible children; so you could set this to 50%, so each box would take half the height of boxes (since your flex-direction is set to column).
There is of course some implementation to do to adapt this to your project, but it's worth a shot (and perhaps cleaner?).
Here is a codepen to show you the trick.
EDIT: As #MrBuggy pointed out, this solution won't work in their case, since the boxes container doesn't have a fixed height.
Related
My problem is that I want the flexbox with variable range width, and all works well, but not on the last row. I want the same dimension for all children even where the row is not full of children (the last row).
#products-list {
position:relative;
display: flex;
flex-flow: row wrap;
width:100%;
}
#products-list .product {
min-width:150px;
max-width:250px;
margin:10px 10px 20px 10px;
flex:1;
}
I created a dynamic situation in jsFiddle
My flex divs can shrink until 150px and grow up to 250px, but all must be with the same size (and obviously I want a CSS solution, with JS I know the way).
Unfortunately, in the current iteration of flexbox (Level 1), there is no clean way to solve the last-row alignment problem. It's a common problem.
It would be useful to have a flex property along the lines of:
last-row
last-column
only-child-in-a-row
alone-in-a-column
This problem does appear to be a high priority for Flexbox Level 2:
CSS Working Group Wiki - Specification Issues and Planning
https://lists.w3.org/Archives/Public/www-style/2015Jan/0150.html
Although this behavior is difficult to achieve in flexbox, it's simple and easy in CSS Grid Layout:
Equal width flex items even after they wrap
In case Grid is not an option, here's a list of similar questions containing various flexbox hacks:
Properly sizing and aligning the flex item(s) on the last row
Flex-box: Align last row to grid
Flexbox wrap - different alignment for last row
How can a flex item keep the same dimensions when it is forced to a new row?
Selector for an element alone in a row?
Aligning elements in last flexbox row
How can I allow flex-items to grow while keeping the same size?
Left-align last row of flexbox using space-between and margins
Inconsistent margin between flex items on last row
How to keep wrapped flex-items the same width as the elements on the previous row?
How to align left last row/line in multiple line flexbox
Last children of grid get giant gutter cause of flexbox space-between
Managing justify-content: space-between on last row
Flexbox space between behavior combined with wrap
Possible to use CSS Flexbox to stretch elements on every row while maintaining consistent widths?
As a quick and dirty solution one can use:
.my-flex-child:last-child/*.product:last-child*/ {
flex-grow: 100;/*Or any number big enough*/
}
You could try using grid instead of flexbox here:
#products-list {
display: grid;
grid-gap: 5px;
grid-template-columns: repeat(auto-fit, minmax(100px, 250px)); //grid automagic
justify-content: start; //start left
}
Fiddle link
There is a great solution that works always.
add a div with class product (The same class for other items that are under flex) and add a style for this div:height:0px;
you need to add as many dives that are possible to be in one row.
<div class="product" style="height:0px">
as many that can be in one row.
That's all. Works always.
If all your rows have the same number of items, you can use :nth-last-child. For example, if all the rows have 3 items, you can do something like this to remove the margin of the last 3 items:
.container{
display: flex;
flex-wrap: wrap;
background: yellow;
}
.item{
width: calc((100% - 2*10px)/3);
height: 50px;
background: blue;
color: white;
margin-right: 10px;
margin-bottom: 10px;
padding: 5px;
box-sizing: border-box;
}
/* last item of each row */
.item:nth-child(3n){
margin-right: 0;
font-size: 150%;
}
/* last 3 items */
.item:nth-last-child(-n+3){
margin-bottom: 0;
background: green;
}
<div class="container">
<div class="item" >1</div>
<div class="item" >2</div>
<div class="item" >3</div>
<div class="item" >4</div>
<div class="item" >5</div>
<div class="item" >6</div>
<div class="item" >7</div>
</div>
A simple trick adds a flexible space to fill the rest of the last row:
#products-list{
display:flex;
flex-flow: row wrap;
justify-content:space-between;
}
#products-list::after {
content: "";
flex: auto;
flex-basis: 200px;/*your item width*/
flex-grow: 0;
}
But you shouldn't use margins on items then. Rather wrap them into containers with padding.
I used this workaround, even if it's not very elegant and it doesn't use the power of Flexbox.
It can be carried out on the following conditions:
All the items have the same width
The items have a fixed width
You use SCSS/SASS (can be avoided though)
If this is the case, you can use the following snippet:
$itemWidth: 400px;
$itemMargin: 10px;
html, body {
margin: 0;
padding: 0;
}
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0 auto;
border: solid 1px blue;
}
#for $i from 1 through 10 {
#media only screen and (min-width: $i * $itemWidth + 2 * $i * $itemMargin) {
.flex-container {
width: $i * $itemWidth + 2 * $i * $itemMargin;
}
}
}
.item {
flex: 0 0 $itemWidth;
height: 100px;
margin: $itemMargin;
background: red;
}
<div class="flex-container">
<div class="item"></div>
<div class="item" style="flex: 500 0 200px"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Here I have created an example on codepen which also implements margin.
The second and the third conditions can be avoided respectively using css variables (if you decided to provide support for it) and compiling the above scss snippet.
Well, it's true, we could do it also before flexbox, but display: flex can be still essential for a responsive design.
I was facing this same issue where I wanted to have a variable number of items in a resizable container.
I wanted to use all of the horizontal space, but have all of the flex items at the same size.
I ultimately came up with a javascript approach that dynamically added padding spacers as the container was resized.
function padLastFormRow() {
let topList = [];
let nSpacersToAdd = 0;
$('#flexContainer').find('.formSpacer').remove();
$('#flexContainer').find('.formItem').each(function(i, formItem) {
topList.push($(formItem).position().top);
});
let allRowLengths = getFlexLineLengths(topList);
let firstRowLength = allRowLengths[0];
let lastRowLength = allRowLengths[((allRowLengths.length) - 1)];
if (lastRowLength < firstRowLength) {
nSpacersToAdd = firstRowLength - lastRowLength ;
}
for (var i = 1; i <= nSpacersToAdd; i ++) {
$('#flexContainer').append(formSpacerItem);
}
}
Please see my Fiddle:
http://jsfiddle.net/Harold_Buchman/z5r3ogye/11/
I was having a similar challenge with menu rows. I wanted more spacing on the top of the second row of menu items.
The use of flex-box's row-gap worked well.
https://developer.mozilla.org/en-US/docs/Web/CSS/row-gap
.menu {
display: flex;
flex-wrap: wrap;
row-gap: 10px;
}
This added a margin-top type effect to menu items were wrapped to the second line.
If all your rows have the same number of items, you can use :nth-last-child. For example, if all the rows have 3 items, you can do something like this:
.container{
display: flex;
flex-wrap: wrap;
background: yellow;
}
.item{
width: calc((100% - 2*10px)/3);
height: 50px;
background: blue;
color: white;
margin-right: 10px;
margin-bottom: 10px;
padding: 5px;
box-sizing: border-box;
}
// last item of each row
.item:nth-child(3n){
margin-right: 0;
background: green;
}
// last 3 items
.item:nth-last-child(-n+3){
margin-bottom: 0;
font-size: 150%;
}
<div class="container">
<div class="item" >1</div>
<div class="item" >2</div>
<div class="item" >3</div>
<div class="item" >4</div>
<div class="item" >5</div>
<div class="item" >6</div>
<div class="item" >7</div>
</div>
This question already has answers here:
JavaScript and getElementById for multiple elements with the same ID
(13 answers)
Closed 1 year ago.
Good day,
I have a CSS grid of 9 square divs, and I would like to add a click event for all of them so that their color changes from limegreen to black, and then changes back to limegreen when the mouse leaves. I am able to do so if I give each div a unique ID and use .addEventListener, but then the issue is I have to write a click event for each div. When I try to give each div the same ID and use .addEventListener, the click event only happens with the first div.
I have spent the past hour or two searching Stackoverflow, Google, forums, and other websites, along with tinkering with my code based on what I've found, but I can't find anything that has helped so far.
Here is my code, but I've only included the HTML/CSS for the first two divs, since the rest of the divs are like the 2nd div and don't respond to clicks:
const dude = document.getElementById("dude");
dude.addEventListener("click", function(){
dude.style.backgroundColor = "black";
});
dude.addEventListener("mouseleave", function(){
dude.style.backgroundColor = "limegreen";
})
.container {
display: grid;
margin: 7rem;
position: relative;
grid-template-columns: auto auto auto;
align-items: center;
justify-content: center;
column-gap: 2.5rem;
row-gap: 2.5rem;
}
.box {
background: limegreen;
width: 10rem;
height: 10rem;
position: relative;
}
.box2 {
background: limegreen;
width: 10rem;
aspect-ratio: 1/1;
position: relative;
}
<div class="container">
<div class="box" id="dude"></div>
<div class="box2" id="dude"></div>
</div>
Thank you very much for your help!
In HTML, two or more elements cannot have the same ID.
In your HTML, add a common class to the div(s) inside of .container.
<div class="container">
<div class="box gridbox"></div>
<div class="box2 gridbox"></div>
</div>
Now use this Javascript code:
/**
* Use this because we're getting the elements with
* their class, not id. This method returns an array
* of the elements with matching class.
*/
const dudes = document.getElementsByClassName("gridbox");
/** Loop over the whole array */
for(let dude of dudes){
/** Add click event handler */
dude.addEventListener("click", () => {
dude.style.backgroundColor = "black";
});
/** Add mouseleave event handler */
dude.addEventListener("mouseleave", () => {
dude.style.backgroundColor = "limegreen";
});
}
This should work fine.
I'm trying to create a collapsible divs (arranged in a column) which takes always the same height when open.
For example, if one div is open, it takes 100% of the height. If two are open, each takes 50% etc.
I set flex-grow: 1 on each div, but the one with bigger content is always higher then others. I tried also to set
fles-basis: 0, but then they do not open at all.
Here is the link to my minimal example: https://codesandbox.io/s/nifty-meadow-hyr31
In your Collapsible.module.css add height=100vh to open style:
.open {
overflow: auto;
height: 100vh;
}
To explain why the solution above works, one vh is equal to 1% of the viewport, the browser will always compute the values in pixels, to see a simple example :
one = document.querySelector('.one');
two = document.querySelector('.two');
one.innerText = one.clientHeight;
two.innerText = two.clientHeight;
body {
height: 100vh;
display: flex;
flex-direction: column;
}
div {
height: 100vh;
}
.one {
background-color: chocolate;
}
.two {
background-color: cyan;
}
.three {
background-color: darkgray;
}
<div class="one">one</div>
<div class="two">two</div>
If you add a third div with a class 'three' the browser will assign each the third of the available height of the viewport. 100vh is not an absolute measure, the only absolute values are the one you put in pixels (although even that can change sometimes if your elements are not considered responsive enough by the browser).
I'm using display flex to display multiple items in one big container (parentDiv). The code is working fine but I get big problems with horizontal centering the items (especially If there are only a few items they should get horizontally centered) so I was using justify-content what leads to big issues:
The parent div is not able to display all items anymore. The first item that gets displayed is the item "04" while it should be "01". How to avoid this?
Please have a look at this code:
#bigDiv {
position: absolute;
width: 100%;
height: 100%;
}
#parentDiv {
width: 90%;
height: 50%;
overflow-y: hidden;
overflow-x: scroll;
text-align: center;
white-space: nowrap;
background: red;
display: flex;
justify-content: center;
align-items: center;
}
.item {
color: white;
background: blue;
flex: 0 0 4%;
margin: 0 3%;
}
.item::after {
content: "";
display: block;
padding-bottom: 100%;
}
<div id="bigDiv">
<div id="parentDiv">
<div class="item">01</div>
<div class="item">02</div>
<div class="item">03</div>
<div class="item">04</div>
<div class="item">05</div>
<div class="item">06</div>
<div class="item">07</div>
<div class="item">08</div>
<div class="item">09</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
<div class="item">13</div>
<div class="item">14</div>
<div class="item">15</div>
<div class="item">16</div>
</div>
</div>
See this image:
My intentions: The parent div should be able to show all of the items (starting with "01" - and the last element should be the "16"-one)
Note: If there are only 4 or less items they should get centered horizontally. (The reason why I added justify-content).
You're fiting 160% into 100%. And you want it centered. And it works: the 160% total width of the resulting children is nicely centered.
But you're also expecting whatever is outside the parent to be accessible.
It's pretty much like making a child element go outside of its parent by -30% to the left or to the top (by any other method) and expecting the parent to allow you to scroll to it. It's not going to happen!
If it did, the child would no longer be placed at -30%, it would be placed at 0%. Scrollbars will never scroll to left or top negative space. It's by design. You need to take it into consideration when designing your page.
Whenever you center a bigger child into a smaller parent you won't be able to use parent's scrollbars to scroll to the beginning of the child. So anything preventing the child positioning in the parent's left negative space will fix it.
I am working on a nested flexbox layout which should work as follows:
The outermost level (ul#main) is a horizontal list that must expand to the right when more items are added to it. If it grows too big, there should be a horizontal scroll bar.
#main {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
overflow-x: auto;
/* ...and more... */
}
Each item of this list (ul#main > li) has a header (ul#main > li > h2) and an inner list (ul#main > li > ul.tasks). This inner list is vertical and should wrap into columns when needed. When wrapping into more columns, its width should increase to make room for more items. This width increase should apply also to the containing item of the outer list.
.tasks {
flex-direction: column;
flex-wrap: wrap;
/* ...and more... */
}
My problem is that the inner lists don't wrap when the height of the window gets too small. I have tried lots of tampering with all the flex properties, trying to follow the guidelines at CSS-Tricks meticulously, but no luck.
This JSFiddle shows what I have so far.
Expected result (what I want):
Actual result (what I get):
Older result (what I got in 2015):
UPDATE
After some investigation, this is beginning to look like a bigger issue. All major browsers behave the same way, and it has nothing to do with my flexbox design being nested. Even simpler flexbox column layouts refuse to increase the list's width when the items wrap.
This other JSFiddle clearly demonstrates the problem. In current versions of Chrome, Firefox and IE11, all items wrap correctly; the list's height increases in row mode, but its width does not increase in column mode. Also, there is no immediate reflow of elements at all when changing the height of a column mode, but there is in row mode.
However, the official specs (look specifically at example 5) seem to indicate that what I want to do should be possible.
Can someone come up with a workaround to this problem?
UPDATE 2
After a lot of experimenting using JavaScript to update the height and width of various elements during resize events, I have come to the conclusion that it is too complex and too much trouble to try to solve it that way. Also, adding JavaScript definitely breaks the flexbox model, which should be kept as clean as possible.
For now, I'm falling back to overflow-y: auto instead of flex-wrap: wrap so that the inner container scrolls vertically when needed. It is not pretty, but it is one way forward that at least does not break useability too much.
The Problem
This looks like a fundamental deficiency in flex layout.
A flex container in column-direction will not expand to accommodate additional columns. (This is not a problem in flex-direction: row.)
This question has been asked many times (see list below), with no clean answers in CSS.
It's hard to pin this as a bug because the problem occurs across all major browsers. But it does raise the question:
How is it possible that all major browsers got the flex container to
expand on wrap in row-direction but not in column-direction?
You would think at least one of them would get it right. I can only speculate on the reason. Maybe it was a technically difficult implementation and was shelved for this iteration.
UPDATE: The issue appears to be resolved in Edge v16.
Illustration of the Problem
The OP created a useful demo illustrating the problem. I'm copying it here: http://jsfiddle.net/nwccdwLw/1/
Workaround Options
Hacky solutions from the Stack Overflow community:
"It seems this issue cannot be solved only with CSS, so I propose you a JQuery solution."
"It's curious that most browsers haven't implemented column flex containers correctly, but the support for writing modes is reasonably good. Therefore, you can use a row flex container with a vertical writing mode."
More Analysis
Chromium Bug Report
Mark Amery's answer
Other Posts Describing the Same Problem
Flex box container width doesn't grow
How can I make a display:flex container expand horizontally with its wrapped contents?
Flex-flow: column wrap. How to set container's width equal to content?
Flexbox flex-flow column wrap bugs in chrome?
How do I use "flex-flow: column wrap"?
Flex container doesn't expand when contents wrap in a column
flex-flow: column wrap, in a flex box causing overflow of parent container
Html flexbox container does not expand over wrapped children
Flexbox container and overflowing flex children?
How can I make a flexbox container that stretches to fit wrapped items?
Flex container calculating one column, when there are multiple columns
Make container full width with flex
Flexbox container resize possible?
Flex-Wrap Inside Flex-Grow
Flexbox grow to contain
Expand flexbox element to its contents?
flexbox column stretch to fit content
https://stackoverflow.com/q/48406237/3597276
flex-flow: column wrap doesn't stretch the parent element's width
Why doesn't my <ul> expand width to cover all the <li>?
https://stackoverflow.com/q/55709208/3597276
Flexbox wrap not increasing the width of parent?
Absolute Flex container not changing to the correct width with defined max-height
Late to the party, but was still running into this issue YEARS later. Ended up finding a solution using grid. On the container you can use
display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(6, auto);
I have an example on CodePen that toggles between the flexbox issue and the grid fix: https://codepen.io/MandeeD/pen/JVLdLd
CSS-only workaround
Nearly 6 years after this question was asked, this flexbox bug still exists, so here's a CSS-only flex-direction: column workaround for anyone else that ends up here:
body {
background-color: grey;
}
button {
background-color: white;
border: none;
border-radius: 4px;
width: 80px;
height: 40px;
margin: 4px;
}
/* WORKAROUND FOR flex-direction: column WITH WRAP IS BELOW */
.wrapped-columns {
flex-direction: row;
flex-wrap: wrap;
writing-mode: vertical-lr;
text-orientation: upright;
}
/* Ensures content is rendered correctly in Firefox */
.wrapped-columns * {
writing-mode: horizontal-tb;
}
<div class="wrapped-columns">
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>
<button>Button 4</button>
<button>Button 5</button>
<button>Button 6</button>
<button>Button 7</button>
<button>Button 8</button>
<button>Button 9</button>
<button>Button 10</button>
<button>Button 11</button>
<button>Button 12</button>
<button>Button 13</button>
<button>Button 14</button>
</div>
This workaround gives the same outcome as flex-direction: column and works with both flex-wrap: wrap and wrap-reverse.
I just found a really awesome PURE CSS workaround here.
https://jsfiddle.net/gcob492x/3/
The tricky: set writing-mode: vertical-lr in the list div then writing-mode: horizontal-tb in the list item. I had to tweak the styles in the JSFiddle (remove a lot of the alignment styles, which aren't necessary for the solution).
Note: the comment says it only works in Chromium-based browsers, and not Firefox. I've only personally tested in Chrome. It's possible either there's a way to modify this to make it work in other browsers or there have been updates to said browsers that make this work.
Big shoutout to this comment: When flexbox items wrap in column mode, container does not grow its width. Digging through that issue thread led me to https://bugs.chromium.org/p/chromium/issues/detail?id=507397#c39 which led me to this JSFiddle.
It is unfortunate that so many major browsers suffer from this bug after many years. Consider a Javascript workaround. Whenever the browser window resizes, or content is added to the element, execute this code to get it to resize to the proper width. You can define a directive in your framework to do it for you.
element.style.flexBasis = "auto";
element.style.flexBasis = `${element.scrollWidth}px`;
Since no solution or proper workaround was suggested yet, I managed to obtain the requested behavior with a little different approach. Instead of separating the layout into 3 different divs, I'm adding all the items into 1 div and creating the separation with some more divs in between.
The proposed solution is hard coded, assuming we have 3 sections, but can be extended to a generic one. The main idea is to explain how we can achieve this layout.
Adding all the items into 1 container div that uses flex to wrap the items
The first item of each "inner container" (I'll call it a section) will have a class, which helps us to do some manipulations that create the separation and styling of each section.
Using :before on each first item, we can locate the title of each section.
Using space creates the gap between the sections
Since the space won't cover the full height of the section I'm also adding :after to the sections so positioning it with absolute position and white background.
To style the background color of each section I'm adding another div inside the first item of each section. I will be position with absolute as well and will have z-index: -1.
To get the correct width of each background, I'm using JS, setting the correct width, and also adding a listener to resize.
function calcWidth() {
var size = $(document).width();
var end = $(".end").offset().left;
var todoWidth = $(".doing-first").offset().left;
$(".bg-todo").css("width", todoWidth);
var doingWidth = $(".done-first").offset().left - todoWidth;
$(".bg-doing").css("width", doingWidth);
var doneWidth = $(".end").offset().left - $(".done-first").offset().left;
$(".bg-done").css("width", doneWidth + 20);
}
calcWidth();
$(window).resize(function() {
calcWidth();
});
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 120px;
align-content: flex-start;
padding-top: 30px;
overflow-x: auto;
overflow-y: hidden;
}
.item {
width: 200px;
background-color: #e5e5e5;
border-radius: 5px;
height: 20px;
margin: 5px;
position: relative;
box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.75);
padding: 5px;
}
.space {
height: 150px;
width: 10px;
background-color: #fff;
margin: 10px;
}
.todo-first:before {
position: absolute;
top: -30px;
height: 30px;
content: "To Do (2)";
font-weight: bold;
}
.doing-first:before {
position: absolute;
top: -30px;
height: 30px;
content: "Doing (5)";
font-weight: bold;
}
.doing-first:after,
.done-first:after {
position: absolute;
top: -35px;
left: -25px;
width: 10px;
height: 180px;
z-index: 10;
background-color: #fff;
content: "";
}
.done-first:before {
position: absolute;
top: -30px;
height: 30px;
content: "Done (3)";
font-weight: bold;
}
.bg-todo {
position: absolute;
background-color: #FFEFD3;
width: 100vw;
height: 150px;
top: -30px;
left: -10px;
z-index: -1;
}
.bg-doing {
position: absolute;
background-color: #EFDCFF;
width: 100vw;
height: 150px;
top: -30px;
left: -15px;
z-index: -1;
}
.bg-done {
position: absolute;
background-color: #DCFFEE;
width: 10vw;
height: 150px;
top: -30px;
left: -15px;
z-index: -1;
}
.end {
height: 150px;
width: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item todo-first">
<div class="bg-todo"></div>
Drink coffee
</div>
<div class="item">Go to work</div>
<div class="space"></div>
<div class="item doing-first">
<div class="bg-doing"></div>
1
</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="space"></div>
<div class="item done-first">
<div class="bg-done"></div>
1
</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="end"></div>
</div>
I solved my issue in this manner I hope it helps someone else that stumbles on thid :
_ensureWidth(parentElement) {
let totalRealWidth = 0;
let parentElementBoundingRect = parentElement.getBoundingClientRect()
let lowestLeft = parentElementBoundingRect.x;
let highestRight = parentElementBoundingRect.width;
for (let i = 0; i < parentElement.children.length; i++) {
let { x, width } = parentElement.children[i].getBoundingClientRect();
if (x < lowestLeft) {
lowestLeft = x;
}
if (x + width > highestRight) {
highestRight = x + width;
}
}
totalRealWidth = highestRight - lowestLeft;
parentElement.style.width = `${totalRealWidth}px`;
}
Workaround :
using javascript its not hard to set the wrapper's width manually after elements have loaded on the screen. The width would always be the last child element's right hand point.
In react i have it updated on the layout changes based on any children being added to the flex wrapper , but this could be called at any point you add or remove children to the wrapper .
let r = refWrapper.current.lastElementChild.getBoundingClientRect()
refWrapper.current.style.width = (r.x+r.width )+'px'
`
where refWrapper is your your flex element
Possible JS solution..
var ul = $("ul.ul-to-fix");
if(ul.find("li").length>{max_possible_rows)){
if(!ul.hasClass("width-calculated")){
ul.width(ul.find("li").eq(0).width()*ul.css("columns"));
ul.addClass("width-calculated");
}
}