I'm having trouble getting a text div
to fit alongside a group of images in a flexbox
row. These siblings currently only respect the column-width
property of the text div
as if it's a total width and overlap any width it has beyond this at various window sizes. The number of images and the length of the text is dynamic, as the content can change on page load. The layout is also responsive so I don't have the luxury of fixed dimensions in many cases. I believe I've reduced the problem to a working example with the following:
HTML:
<div id='maincontainer'>
<div id='text'>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam quibus rebus efficiuntur voluptates, eae non sunt in potestate sapientis. In his igitur partibus duabus nihil erat, quod Zeno commutare gestiret. At cum de plurimis eadem dicit, tum certe
de maximis. Pugnant Stoici cum Peripateticis. Qua tu etiam inprudens utebare non numquam. Duo Reges: constructio interrete.</p>
<p>Beatus autem esse in maximarum rerum timore nemo potest. Quid est, quod ab ea absolvi et perfici debeat? Quarum ambarum rerum cum medicinam pollicetur, luxuriae licentiam pollicetur. Tubulum fuisse, qua illum, cuius is condemnatus est rogatione, P.
Si id dicis, vicimus. Cur post Tarentum ad Archytam? Que Manilium, ab iisque M.</p>
</div>
<img class='img__gallery' src='https://placehold.it/200x300/a00/fff'>
<img class='img__gallery' src='https://placehold.it/200x300/a00/fff'>
<img class='img__gallery' src='https://placehold.it/200x300/a00/fff'>
<img class='img__gallery' src='https://placehold.it/200x300/a00/fff'>
</div>
CSS:
#maincontainer {
display: flex;
position: absolute;
min-height: 300px;
max-height: 550px;
height: 100%;
width: 800px; // not in original. Used to force the issue to show.
}
#text {
position: relative;
display: block;
padding-left: 20px;
padding-right: 20px;
column-width: 160px;
height: 100%;
column-gap: 20px;
column-fill: auto;
}
.img__gallery {
position: relative;
display: block;
margin-right: 20px;
}
Codepen: https://codepen.io/anon/pen/ModaEN
As intended, the text appears before the images. It creates however many columns of 160px it needs to fit the text content in. However, the images don't start after the text content, but overlap the div (you can barely make out the majority of the text div peaking out behind the images in the CodePen example). There's a solution to this also through javascript but it feels OTT. Surely a multi-column text div can make room for itself inside a flexbox without other items crowding over it?
In other words:
Is there a way for the flex items inside #maincontainer
to respect and make room for the total width of #text
(while #text
respects its own column-width
property at all window sizes)?
Currently, either the other flex items (the images) overlap and don't respect the total width of #text
, or else #text
shrinks its columns to sizes much smaller than column-width
at smaller window sizes. Given that I've stated a column-width
(160px) for #text
, the next flex item should begin at 480px + padding, etc. to the right of the text if #text
has 3 columns. 640px+padding if it has 4, etc.
If anybody is having trouble interpreting what I mean by respect, I'm inferring the action of making room for it. If an element's width ends at 200px, its next sibling should start at 200px+, etc. It's the behaviour most designers would be familiar with from relative positioning and/or floats. It's also the usual behaviour in flexboxes.
Querying the element width of #text
in javascript (well, jquery, using $("#textcontainer").width();
) returns a value identical to my specified column-width
value.
Javascript (and therefore, I guess, the browser) is seeing the total width of the #text
element as the column-width
value, which would make some sense of why the neighbouring flex items are overlapping #text
up to the width of one column. I've confirmed this in both Chrome and Safari on the latest releases of both on macOS.
I've actually made a working solution using javascript but would still be eager to avoid using it. It just seems a bit ridiculous that this basic composition need is as convoluted to solve as this.
I'm not sure how this illustration better clarifies 'I need the sibling images to respect the total width of #text
rather than overlapping it', but I'm including it incase it does, as requested. A is the required solution at all window sizes, B is what's happening:
If you want to have a fixed-width column with Flexbox, you need to use the CSS flex or flex-basis property. First of all, we set the display of our <div> container to "flex". Then, we specify the flex of the "grey" class as "0 0 50px".
For 3 items per row, add on the flex items: flex-basis: 33.333333% You can also use the flex 's shorthand like the following: flex: 0 0 33.333333% => which also means flex-basis: 33.333333% .
The flex-grow property If we gave all of our items in the example above a flex-grow value of 1 then the available space in the flex container would be equally shared between our items and they would stretch to fill the container on the main axis. The flex-grow property can be used to distribute space in proportion.
AFAIK CSS columns and flexbox are basically incompatible with each other. A flex container takes no notice of column declarations. It would appear that giving an element columns effectively takes it out of the flex flow, hence why it allows the text to overlap with the other elements in the container.
I haven't read the specs for either to say in enough detail whether this behaviour is by design or not, it's just what I can observe. Sadly I think if you need the CSS columns in your div you will have go down the script route in order to correct it. I could be wrong but haven't seen a way round it as yet.
As IlyaStreltsyn pointed out, there's a also a bug with column-oriented flex containers (https://github.com/philipwalton/flexbugs#14-flex-containers-with-wrapping-the-container-is-not-sized-to-contain-its-items) which may be related to this as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With