Flex right and left division with certain gap in the middle

image

If we have to make a certain design where we have to divine available space such that in one row only two flex items are to be retained.

I think this property will do the needful:
flex: 1 0 50%;
flex-wrap: wrap, but this doesn’t give a gap between the two left and right.
Either we give padding-left ton flex right element or
we give padding-right to the flex left element.

Margin may be the other rescue.

Another alternative will be to give a middle div in the middle and set margin/padding or certain fix width there so that in case of swap of flex-direction still the middle, space remains the same.

flex

This is what I know. Is there any evolved and more professional way to cater to such situations?

You need to consider how your 8 elements will appear on small smartphones. If you use “50%” the elements will shrink down to rather narrow widths.

I suggest you use flex:0 1 350px; (but edit 350 if you wish). Having the flex-shrink set to “1” will allow the width to shrink as necessary on small smartphones. With the flex-grow set to “0” the elements will never be wider than 350 pixels.

If the 8 elements have no margins: within any container less than 700 pixels wide there will be only one element in each flexbox row, so there will be 8 rows. If a container is between 700 and 1049 pixels wide there will be two elements in each row, so there will be 4 rows. If you want to avoid having 3 or more elements on each row you will need to constrain the width of the container.

Use CSS justify-content property to control how any spare space between elements on a row is distributed. Do not use a div element to provide spacing.

If your elements had borders, you would want to use CSS padding to keep the text clear of the borders. Also you would want to use CSS margin to prevent the element boxes touching each other.

There is more to flexbox than this :smile:

1 Like

If all you want is 2 columns and a consistent gap in the middle only then use flex-basis with calc.

e.g. flex-basis: calc(50% - 1rem);

Combined with justify-content:space-between on the parent you will get a consistent 2 rem gap in the middle.

.wrap {
  display: flex;
  flex-wrap: wrap;
  background: #eee;
  max-width: 1280px;
  margin: auto;
  justify-content: space-between;
}
.wrap > div {
  flex-basis: calc(50% - 1rem);
  padding: 10px;
  background: #f9f9f9;
  border: 1px solid red;
  margin: 0 0 1rem;
}

Avoid empty divs at all costs and unless there is no other alternative.:slight_smile:

Also if you only have two flex children rather than multiple children as in the last example you could just use gap to get the space.

See second example here:

Also note that in the above examples if you don’t want inner elements to push the columns wider than the 50% then (perversely) you need to add min-width:0 to the column;

min-width:0;/* stops element from flexing if inner content is wider*/

3 Likes

Hi there sir, Is there any major issue that I need to know to avoid such things?

Smartphones can have a width of only 320 pixels (CSS pixels, not device pixels), so a two-column layout with space in the middle is poor. It’s far better to make use of the capabilities of CSS Flexbox so that on small screens you will get just one column displayed. An empty <div> element to provide horizontal spacing on larger screens would mess up the display on small screens. Far better to use the options available in the CSS justify-content property, with some use of CSS margin to avoid boxes touching each other. I use percentage values for left and right margins so margins are smaller on small screens.

However, I sometimes use empty <div> elements where the flex-direction is column. This enables me to display visual separators. Perhaps that is rather naughty and I should be using SVG elements as decorative images instead (or HTML <hr> elements).

If you must use a <div> as a separator, you should consider adding HTML attribute role="separator". That’s what I do!

I suggest you try to make use of the power of Flexbox to give flexible layouts that can automatically adapt very well to a wide range of screen widths.

1 Like

No, there is no real issue with adding empty elements apart from semantics and maintenance of course but generally you can do what you require without resorting them.

Sometimes though you do need need to add an empty element when you have no other choice and then it’s fine as long as crafted correctly.

However I often see posted in the forums code that has many empty elements when in fact none was needed. It should therefore not be a tool that you reach for at every occasion. The html should be as semantic as possible with no wastage and only if there is no other way to do what you want then feel free to add extra elements.

Yes I agree for text content you probably want to go to one column on smaller screens.

If its just a small image side by side or a few words either side then 2 columns may suffice. It all depends on the situation but most screens under 400px (magic number alert) would benefit from a single column as you can ensure the content text is slightly larger as well as text on a mobile at 1rem is harder to read than text on a desktop at 1rem especially for old people with glasses like me :slight_smile:

In the end its nothing to do with screen size but the simple question of how much space does this design need to look and work well at every pixel width. Look at your design. Is it squashed or too spaced out. If so then adjust it. Do that for every pixel from 320px to your max-width xxpx. :wink:

1 Like

There is a certain situation like this:

<div class="wrapper">
	<section class="sidebar">
		Lorem ipsum, dolor, sit amet consectetur adipisicing elit. Distinctio ratione vero cupiditate quaerat, nam, corrupti impedit dolor! Obcaecati incidunt quas officia, quisquam perferendis facere est, veritatis fuga dicta, necessitatibus quia.
	</section>
	<section class="article">
		Lorem ipsum dolor, sit amet, consectetur adipisicing elit. Animi esse culpa omnis voluptate alias laboriosam accusamus magnam tenetur corrupti. Inventore pariatur, eos quod nesciunt eaque vitae iste recusandae quidem officia.
	</section>
</div>

CSS:

.wrapper {
  display: flex;
}
.sidebar {
  flex: 1 0 calc(30% - 100px);
  padding: 20px;
  border: 2px solid #000000;
}
.article {
  flex: 1 0 calc(70% - 100px);
  padding: 20px;
  border: 2px solid #000000;
}

still not getting the middle gap between the two div:

Add CSS margin.

1 Like

This part is useless than →

?

You’ve set flex-grow to 1 which means it will grow to fill the available space. There will be no gap.

Flex-basis is only a minimum basis when you have flex-grow to 1. Set flex-grow to zero and then the basis will be applied exactly.

.wrapper {
  display: flex;
  justify-content:space-between;
}
.sidebar {
  flex: 0 0 calc(30% - 100px);
  padding: 20px;
  border: 2px solid #000000;
}
.article {
  flex: 0 0 calc(70% - 100px);
  padding: 20px;
  border: 2px solid #000000;
}

Then just justify-content:space-between; on the wrapper.

1 Like

I tried one more thing:

.sidebar {
  flex: 1 0 calc(30% - 100px);
  max-width: 350px;
  padding: 20px;
  border: 2px solid #000000;
  overflow-y: scroll;
  left: 0;
  top: 0;
  bottom: 0;
  position: fixed;
  overflow-y: auto;
  overflow-x: hidden;
}
.article {
  flex: 1 0 calc(70% - 100px);
  padding: 20px;
  border: 2px solid #000000;
}

Then suffered a design breakdown →

That doesn’t make sense. :slight_smile:

A fixed position element will not take part in the flex flow. You would need to position the flex container away from the fixed element.

I’d need to see exactly what you are trying to do before offering a solution as there could be many ways to approach this. :slight_smile:

1 Like

Sir, I am attempting to create simple two-column template on this line.

This is just off the top of my head but there are likely many other ways to do this.:slight_smile:

1 Like

Sir, what technical qualification does this have here:

.wrapper:before {
  content: "";
  width: 30%;
  flex: 0 0 30%;
  max-width: 350px;
  position: relative;
  z-index: -1;
}

It creates the space to match the width of the fixed menu otherwise the article column will overlap the fixed position menu.

Fixed elements are removed from the flow so you have to purposely avoid them with your in-flow content.

1 Like

This is roughly how I would do it:

Much less CSS!

2 Likes

I got that sir, but technically I think some pseudo parent container was imagined which was given position relative, and then the inner sidebar was given the position absolute.

But still I am unable to mentally analyze that how the scheme of order is working, slightly confused over that pseudo element.

Give a red background to the pseudo element and you will see what is happening.

e.g.

It’s basically a two column flex layout and then a fixed position element is allowed to sit on the left column while the flow of the page is maintained by the pseudo element.

Otherwise there is no way to push the second column to the right when you have used 30% width and a max-width. i.e. there is no margin-left:300% or max-margin-left 350px. If you didn’t have the max-width in your left column then the pseudo element could be eliminated and the column could just have a percentage left margin.

Or you could use use the gap property instead of margin :slight_smile:

Much less css again :wink:

1 Like