Home  >  Q&A  >  body text

Flex spacing broken when trying to overflow HTML <pre><code> tag instead of wrapping

I apply CSS to the pre code selector in order to make styled code blocks like you would see on GitHub or elsewhere. I'm using Flexbox for layout and have two "panel" divs side by side inside a "box" div, one of which has a code block (this is just the code inside the <pre><code> tag) , and the "box" div is inside the main "container" div.

The basic CSS I have is...

.*, *:before, *:after {
    margin: 0;
    padding: 0;
    box-sizing: inherit;
}

html {
    box-sizing: border-box;
}

body {
    display: flex;
    align-items: center;
    justify-content: center;
}

pre code {
    display: inline-block;
    overflow: auto;
    white-space: pre;
    padding: 1rem;
    margin: 1rem;
}

.container {
    display: flex;
    flex-direction: column;
    margin: 1rem;
    gap: 1rem;
}

.box {
    display: flex;
    flex-direction: row;
    gap: 1rem;
}

.panel {
    display: flex;
    flex-direction: column;
    flex: 0.5;
    padding: 1rem;
}

Since flex: 0.5, both panels should be equal in width, but the right panel expands to fit the block instead of the block shrinking to fit the panel.

If I set white-space: pre-wrap on pre code, I get the desired layout behavior, but of course the code is wrapped, which is what I Unwanted.

Of course, if I use white-space: pre and add a dedicated width to the pre code , I get the desired behavior, where the code block has a horizontal scrollbar. I can't use a dedicated width because I need the block to fit any panels inside it.

For some reason, setting width: 100% on the pre code has no effect at all.

To make sure I wasn't doing something else somewhere that would cause this error, I put together this code to confirm my problem (I did add some background color and margins to make the container visible):

https://codepen.io/evprkr/pen/poKQXJr

P粉277464743P粉277464743183 days ago309

reply all(1)I'll reply

  • P粉621033928

    P粉6210339282024-04-02 11:59:47

    CSS IssuesCause you are experiencing problems:

    1. In the first line of CSS .*, *:before, *:after { }, there is an initial . (dot) that is easy to miss. Therefore the border-box model only works with :before and :after pseudo-elements. Apparently, the same goes for margin and padding.
    2. All .panel ancestors have no width value set, so flexbox cannot constrain child elements and will grow to infinity.
    3. flex: 0.5 (default is flex: 0.5 1 0%) obviously has no effect since it has no width flex-basis: 50%. In both cases, the pre code will not trigger overflow, so the scrollable box will not be displayed. I can't explain why, but it must be due to some W3C specification. However, your declaration of .panel width: 50% finally solved the problem.
    4. Using margins in conjunction with various elements and gap can produce seemingly unexpected overlap of elements when resizing the browser/codepen. Even if the above initial .
    5. is deleted

    solution

    • Advertising 1) Delete .(click)
    • ad 2) Specify .container width: 100% to provide a usable constraint for flexbox.
    • ad 3) Delete .panel flex: 0.5 and specify .panel width: calc(50% - 0.5rem). calc(..) is required because gap will increase the total width of .panels, possibly causing them to overlap when resized. Since your ngap: 1rem adds 0.5rem to each of the two columns, you need to subtract that value from the width of each column.
    • 4) Like ngap, margin increases the overall width of the element, which requires you to subtract the left and/or right margins from the element width to prevent them from overlapping other elements. The easiest way to avoid adding extra calc(..) in CSS is to move the element's margin to its immediate parent's padding. This isn't true in all cases, but in this case it works well without changing the overall layout.

    bonus

    For Response Behavior:

    • Allow .box to wrap its child elements
    • Set some minimum required .panel width to force the .box to wrap its child .panels. In this case I chose 300px.
    • This is required to allow the .panel element to grow to its full 50% when unwrapped.

    Also hyphenate text to improve readability...

    fragment

    *, *:before, *:after {
        margin: 0;
        padding: 0;
        box-sizing: inherit;
    }
    
    html {
        box-sizing: border-box;
    }
    
    body {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    pre code {
        background: #d7d7db;
        display: block;
        overflow: auto;
        white-space: pre;
        padding: 1rem;
    
    }
    
    .container {
        background: #0197f4;
        display: flex;
        flex-direction: column;
        padding: 1rem;
        width: 100%;
    }
    
    .box {
        background: #ff7538;
        display: flex;
        flex-flow: row wrap;
        gap: 1rem;
        padding: 1rem;
    }
    
    .panel {
        background: #fff;
        display: flex;
        flex-direction: column;
        padding: 2rem;
    
        /* Adjust for parent gap value */
        width: calc(50% - 0.5rem);
    
        /* Allow to grow and wrap when less than 300px */
        flex: 1;
        min-width: min(300px, 100%);
    }
    
    .text { hyphens: auto }
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan mattis ullamcorper. Nulla tincidunt aliquam feugiat. Sed imperdiet tellus ligula, vehicula condimentum neque venenatis ut. Aenean varius elementum nulla, vehicula laoreet erat aliquam at. Nullam venenatis ex id tincidunt fringilla. Vivamus nec tellus sit amet leo tristique luctus. Cras elementum at diam at viverra. Phasellus tristique elementum velit id tincidunt. Nullam ullamcorper fringilla nulla sed ultricies.
    function SomeFakeFunction(first_argument, second_argument) {
        if (first_argument > second_argument) {
            return "first argument is greater than second argument";
        } else if (first argument < second_argument) {
            return "first argument is less than second argument";
        }
        
        return "first argument and second argument are equal (or invalid but this is just filler code so i don't care to write anymore honestly)"
    }

    reply
    0
  • Cancelreply