@codeispoetry posted a new topic, subject "Flex right and left division with certain gap in the middle". It read:

   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.
    
    flex707×656 229 KB
    
    This is what I know. Is there any evolved and more professional way to cater to such situations?

Then @Archibald said

    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

After which, @PaulOB added

    codeispoetry:
    
    > This is what I know. Is there any evolved and more professional way to cater to such situations?
    
    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.
    [code] 
        .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;
        }
        
    [/code]
    
    codeispoetry:
    
    > Another alternative will be to give a middle div in the middle and set margin/padding or certain fix width
    
    Avoid empty divs at all costs and unless there is no other alternative.
    
    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*/`

@codeispoetry replied

    PaulOB:
    
    > Avoid empty divs at all costs and unless there is no other alternative.
    
    Hi there sir, Is there any major issue that I need to know to avoid such things?

After which, @Archibald added

    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.

To which @PaulOB replied

    codeispoetry:
    
    > Hi there sir, Is there any major issue that I need to know to avoid such things?
    
    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.
    
    Archibald:
    
    > 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.
    
    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 
    
    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.

Then @codeispoetry said

    There is a certain situation like this:
    [code] 
        <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>
        
    [/code]
    
    CSS:
    [code] 
        .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;
        }
        
    [/code]
    
    still not getting the middle gap between the two div:
    
    image870×378 21.8 KB

To which @Archibald replied

    Add CSS margin.

To which @codeispoetry replied

    Archibald:
    
    > Add CSS margin.
    
    This part is useless than →
    
    codeispoetry:
    
    > `- 100px);`
    
    ?

So @PaulOB replied

    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.
    [code] 
        .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;
        }
        
    [/code]
    
    Then just justify-content:space-between; on the wrapper.

To which @codeispoetry replied

    I tried one more thing:
    [code] 
        .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;
        }
        
    [/code]
    
    Then suffered a design breakdown →
    
    image1363×732 119 KB

@PaulOB replied

    codeispoetry:
    
    > tried one more thing:
    
    That doesn't make sense. 
    
    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.

To which @codeispoetry replied

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

So @PaulOB replied

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

To which @codeispoetry replied

    Sir, what `technical qualification` does this have here:
    [code] 
        .wrapper:before {
          content: "";
          width: 30%;
          flex: 0 0 30%;
          max-width: 350px;
          position: relative;
          z-index: -1;
        }
        
    [/code]

To which @PaulOB replied

    codeispoetry:
    
    > Sir, what `technical qualification` does this have here:
    
    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.

@Archibald replied

    This is roughly how I would do it:
    
    Much less CSS!

Then @codeispoetry said

    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.

Then @PaulOB said

    codeispoetry:
    
    > 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.

After which, @PaulOB added

    Archibald:
    
    > Much less CSS!
    
    Or you could use use the gap property instead of margin 
    
    Much less css again

To which @Archibald replied

    PaulOB:
    
    > Or you could use use the gap property instead of margin
    
    CSS gap (in flex layout) is not supported in Safari.

To which @codeispoetry replied

    Archibald:
    
    > CSS gap (in flex layout) is not supported in Safari.
    
    Any remedial Fix?  
    https://caniuse.com/flexbox-gap

So @PaulOB replied

    Archibald:
    
    > @PaulOB Why don't you like using `margin-right` ?
    
    I didn't say I didn't like it I just preferred that with gap you don't have to use it and don't have to negate it for smaller screens when content wraps etc. Also a margin-right _could_ cause a scrollbar on mobile or squash the content depending on set up. It's not that I dislike margins but gap doesn't suffer from those problems. Obviously in the real world we'd be adjusting with media queries anyway so its a minor point either way.
    
    However for better support margins are the way to go for now until Safari completes their technical review of gap.
    
    Archibald:
    
    > CSS `justify-content:space-between` will push the right-hand box way over to the right on a large screen (unless e.g. `max-width: 1100px` is set on the body). Also the gap will go to zero for a range of screen widths.
    
    I was assuming some sort of page wrapper or centred layout would be required as I dislike left aligned sites as they look a bit awkward on large monitors.
    
    Archibald:
    
    > Also the gap will go to zero for a range of screen widths.
    
    Yes but only at very small sizes and then only because min-width needs to be set to zero (min-width is set to min-content by default in flex I believe). Otherwise the container doesn't shrink to match the size that was set.
    
    e.g.  
    This gap is consistent.
    
    However I'm not saying that's the way I would do it. It all depends on the task in hand so as we have both shown there are many ways to do the same thing but all with their own peculiarities. 
    
    It's all good

To which @Archibald replied

    PaulOB:
    
    > If the space between is important then a margin or justify:space-between will have to do
    
    CSS `justify-content:space-between` will push the right-hand box way over to the right on a large screen (unless e.g. `max-width: 1100px` is set on the body). Also the gap will go to zero for a range of screen widths.
    
    @PaulOB Why don't you like using `margin-right`?

After which, @PaulOB added

    Archibald:
    
    > @PaulOB Why don't you like using `margin-right` ?
    
    Hmm I seem to have edited my last post instead of making a new one 
    
    So my reply is on the post before your last one

Then @PaulOB said

    codeispoetry:
    
    > Any remedial Fix?  
    >  https://caniuse.com/flexbox-gap
    
    Not really.
    
    We can't use @supports because gap is supported in grid and would pass the test. It's flexbox in Safari that doesn't support gap. (I guess the browser makers didn't expect a property to be supported for one layout system but not another.)
    
    The only option for Safari is to use margins or one of the other methods mentioned instead. As I mentioned (before I edited my last post in error) it is under review in Safari so shouldn't be long before its implemented.
    
    Or alternatively use grid where gap is supported in Safari

@Archibald replied

    PaulOB:
    
    > min-width is set to min-content by default in flex I believe
    
    I don't think that is the case. If break-word is not used, to avoid overflow you need to be careful that long words are less than 320px for small smartphones (also allowing for border widths, padding etc).
    
    PaulOB:
    
    > Obviously in the real world we'd be adjusting with media queries anyway
    
    In the real world I don't adjust with any media queries

To which @PaulOB replied

    Archibald:
    
    > I don't think that is the case
    
    No its not actually set to the min-content value as I stated but it is set to **auto** by default which means that any long words or unbroken content will stop the element squashing (in flex items only) which is why the space between was getting smaller. With min-width:0 in place the element will keep on shrinking. Of course there will come a point when things overlap but its a different example to your fixed width column so comparisons are not equivalent.
    
    Here's an example of how min-width:0 makes a difference to flex items just to explain what I meant 
    
    Close the browser window smaller to see the behaviour changes.
    
    Archibald:
    
    > In the real world I don't adjust with any media queries 
    
    Yes that's good if you can manage that but its not always possible. It's a good thing to attempt though so I'm not knocking it

@Archibald replied

    PaulOB:
    
    > This gap is consistent.
    
    To always have 60px gap you need to delete the `max-width: 350px` (because 30% of 1280 is 384).

Then @PaulOB said

    Archibald:
    
    > To always have 60px gap you need to delete the `max-width: 350px` (because 30% of 1280 is 384).
    
    Yes true. I didn't notice that 
    
    Too busy looking at other things.

After which, @Archibald added

    PaulOB:
    
    > Yes that's good if you can manage that but its not always possible. It's a good thing to attempt though so I'm not knocking it
    
    There's a fairly challenging demo of using flexbox with no media queries here: http://create.mywebcommunity.org/demo.html (on some free webspace).
    
    Media queries would improve the aethetic appearance, especially at some browser widths, but with the software I use pages can be created and edited very quickly.

So @PaulOB replied

    Archibald:
    
    > There's a fairly challenging demo of using flexbox with no media queries
    
    Good work :).
    
    I generally say that the simpler you make something the easier it is to manage. Losing the media queries is one less headache to manage :;

To which @codeispoetry replied

    I was willing to write the media query and I encountered the below problem. How can I get rid of pseudo element In media query it is not a class where we can put` display: none`  
    
    
    pseudo1352×656 1.72 MB

Then @PaulOB said

    codeispoetry:
    
    > it is not a class where we can put ` display: none`
    
    Yes you add display:none to the pseudo element with no problems.
    
    `.wrapper:before{display:none;`}
    
    or indeed:
    
    `.wrapper:before {content:none}`
    
    Both will remove the pseudo element completely.

So @codeispoetry replied

    [code]
        <div class="hamburger">
        	<div class="top clicked"></div>
        	<div class="middle clicked"></div>
        	<div class="bottom clicked"></div>
        </div>
        
    [/code]
    [code] 
        .hamburger {
          display: flex;
          gap: 10px;
          flex-direction: column;
          margin: auto;
        }
        .top, .middle, .bottom {
          max-width: 60px;
          max-height: 6px;  
          width: 60px;
          height: 6px;
          background-color: #212121;
        }
        
        .middle.clicked {
          transition-duration: 0.5s;
          background: transparent;
        }
        .top.clicked {
          transform: rotateZ(45deg) scaleX(1.25) translate(13px, 13px);
        }
        .bottom.clicked {
          transform: rotateZ(-45deg) scaleX(1.25) translate(12px, -12px);
        }
        .hamburger:hover {
          cursor: pointer;
        }
        
    [/code]
    
    `margin: auto` is not working on the hamburger.

So @PaulOB replied

    codeispoetry:
    
    > `margin: auto` is not working on the hamburger.
    
    It is working but the hamburger is 100% wide so there is nothing to centre:) (Just give a red background to .hamburger to see what I mean  )
    
    If you want to centre the content then there is a flex rule for that ( align-items:center when column axis in use)
    [code] 
        .hamburger {
          display: flex;
          gap: 10px;
          flex-direction: column;
          margin: auto;
          align-items:center;
        }
        
    [/code]
    
    Or give the hamburger a width to match its content.
    [code] 
        .hamburger {
          display:flex;
          gap: 10px;
          flex-direction: column;
          margin: auto;
          width:60px;
        }
        
    [/code]

So @codeispoetry replied

    Post Update:
    [code] 
        .clicked .top {
          transform: rotateZ(45deg) scaleX(1.25) translate(13px, 13px);
          transition-duration: 0.5s
        }
        .clicked .bottom {
          transform: rotateZ(-45deg) scaleX(1.25) translate(8px, -8px);
          transition-duration: 0.5s
        }
        
    [/code]
    
    Only through the hit and trial was I able to come closer. Still logic not clear how X and Y coordinates are accessed through CSS. I am trying to the browser as many resources as possible to get some clarity. Any help will be appreciated.

So @PaulOB replied

    codeispoetry:
    
    > Still logic not clear how X and Y coordinates are accessed through CSS.
    
    Sorry you lost me 
    
    If you mean translate then its translate(x,y).

So @PaulOB replied

    Note that if you put the transition on the normal state then the menu will animate back to closed rather than just clicking shut.
    
    e.g.
    [code] 
        .top,
        .middle,
        .bottom {
          max-width: 60px;
          max-height: 6px;
          width: 60px;
          height: 6px;
          background-color: #212121;
          transition: transform 0.5s ease;
        }
        
        .clicked .middle {
          background: transparent;
        }
        .clicked .top {
          transform: rotateZ(45deg) scaleX(1.25) translate(13px, 13px);
        }
        .clicked .bottom {
          transform: rotateZ(-45deg) scaleX(1.25) translate(8px, -8px);
        }
        
    [/code]

To which @Archibald replied

    How about this?
    [code] 
        .top:active {
          transform: rotateZ(45deg) scaleX(1.25) translate(13px, 13px);
        }
        .middle:active {
          transition-duration: 0.5s;
          background: transparent;
        }
        .bottom:active {
          transform: rotateZ(-45deg) scaleX(1.25) translate(12px, -12px);
        }
        
    [/code]
    
    BTW there's no need for `.hamberger:hover` selector. The `cursor: pointer` declaration can go in the `.hamburger` selector.

So @codeispoetry replied

    Archibald:
    
    > BTW there's no need for `.hamberger:hover` selector. The `cursor: pointer` declaration can go in the `.hamburger` selector.
    
    Thanks.

After which, @codeispoetry added

    Archibald:
    
    > 
    [code]
    >     .top:active {
    >     
    [/code]
    
    Archibald:
    
    > 
    [code]
    >     .middle:active {
    >     
    [/code]
    
    Archibald:
    
    > 
    [code]
    >     .bottom:active {
    >     
    [/code]
    
    Could not get this point because the class `clicked` is in `body` now. How will the independent class be declared active?

Then @Archibald said

    I didn't find a class named “clicked”.
    
    If you use `:active`, a transition will happen when you click on part of the hamburger. I am not sure if that is what you want

@PaulOB replied

    Archibald:
    
    > :active
    
    `:active` doesn't apply to divs but raise a good point that the hamburger really should be a button element as it creates an action

So @Archibald replied

    PaulOB:
    
    > `:active` doesn't apply to divs
    
    The transition works.

@PaulOB replied

    Archibald:
    
    > The transition works
    
    Sorry I'm not following or I'm probably misunderstanding something 
    
    What has :active got to do with the transition?

Then @Archibald said

    PaulOB:
    
    > What has :active got to do with the transition?
    
    Perhaps I have not examined this lengthy thread in sufficient detail.
    
    What is triggering the transitions if you are not using `:active` or `:hover` or similar?

Then @PaulOB said

    Archibald:
    
    > What is triggering the transitions
    
    Yes its a bit of a convoluted thread to follow and has veered off topic a bit 
    
    There was some JS adding a class when the hamburger was clicked. The class that was added was used to trigger the transition. (There's also a JS thread tied to this question that may help tie up some loose ends.)
    
    However, I believe that part has been resolved satisfactorily now.

Then @ladans37 said

    > `flex-wrap: wrap` , but this doesn't give a gap between the two left and right.
    
    Would a `column-gap:` not resolve the issue?

So @TechnoBear replied

    A post was merged into an existing topic: Flex WRAP discussion

Then @system said

    This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.


{'source': 'discourse', 'url': 'https://www.sitepoint.com/community/t/flex-right-and-left-division-with-certain-gap-in-the-middle/366585', 'title': 'Flex right and left division with certain gap in the middle', 'views': 5573, 'has_accepted_answer': False, 'word_count': 4260, 'like_count': 48, 'reply_count': 31, 'participant_count': 4, 'posts': 51, 'tags': '', 'author': '@codeispoetry', 'participants': '@codeispoetry, @Archibald, @PaulOB, @ladans37, @TechnoBear, @system', 'image_url': ['https://aws1.discourse-cdn.com/sitepoint/original/3X/a/7/a7f969eae004c6947eb694799e60ca52b61aec58.png'], 'created_at': '2021-04-09T03:51:13.949Z', 'last_posted_at': '2021-09-25T20:49:43.090Z'}