Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flexbox compatibility with horizontal pre / code scrolling

Tags:

html

css

flexbox

I have some code inside pre and code tags in a bootstrap container that I'd like to scroll horizontally. This normally works fine, until I add a flexbox to my page's body in order to accomplish a sticky footer. After this, the code no longer scrolls horizontally when the page is narrow (such as for mobile viewing).

Here's my code (note that horizontal scrollbars for the code go away as you narrow the window):

html, body {
    height: 100%;
}
body {
    min-height: 100%;
    display: flex;
    flex-direction: column;
}
code {
    max-height: 200px;
    background-color: #eeeeee;
    word-break: normal !important;
    word-wrap: normal !important;
    white-space: pre !important;
}
.flexer {
    flex: 1;
}
footer {
    background-color: #CCC;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
    <div class="row">
        <div class="col-md-12 docs">
            <p>Some sample code</p>
            <pre><code>Loading mirror speeds from cached hostfilebase: mirrors.arpnetworks.com * centosplus: mirrors.arpnetworks.com* extras:mirrors.arpnetworks.com*rpmforge: mirror.hmc.eduupdates: mirrors.arpnetworks.comExcluding Packages in global exclude list</code></pre>
        </div>
    </div>
</div>
<div class="flexer"></div>
<footer>
    <div class="container">
        <div class="row">
            <div class="col-sm-12 text-center">
            footer
            </div>
        </div>
    </div>
</footer>

http://jsfiddle.net/nturor46/1/

Any idea how to use flexbox for sticky footers while still maintaining scrolling pre / code?

like image 769
Josh Stone Avatar asked Feb 04 '16 06:02

Josh Stone


4 Answers

a simple

.container { width:100%; }

resizes the website correctly. BUT then, Chrome doesn't let you actually use the scrollbar. This is caused by it overflowing the dimension of all of its containers (apart from BODY). Hence we gotta tell the browser to correctly recognize the pre node:

.container {
  max-width: 100%;
}
pre {
  position: relative;
}

This tells Chrome to correctly handle mouse events again AND fixes the layout

Please note that the margin-bottom of the pre-node is lost in overflow-country, which could cause your layout to look weird. max-width was used in the final version to make sure it doesn't overwrite fixed width statements made in bootstrap

PS: tested in current Chrome and Firefox http://jsfiddle.net/nturor46/32/

like image 149
Jörn Berkefeld Avatar answered Sep 29 '22 21:09

Jörn Berkefeld


Those bootstrap styles just wreak havoc on natural CSS!

The problem seems to come from a conflict between your column-direction flex container and bootstrap rules. It's basically resulting in the horizontal scrollbar shifting from the pre / code content box to the browser window, when the content box overflows the screen.

With these adjustments, your desired layout seems to work:

  • make the primary .container div the primary flex container (in your code this role is played by the body element)
  • move the footer element into this new container
  • use flex auto margins to stick the footer to the bottom
  • override bootstrap margin, padding and width wherever necessary

HTML

<div class="container">

    <div class="row">
        <div class="col-md-12 docs">
            <p>Some sample code</p>
            <pre><code>Loading mirror speeds from ... cached hostfilebase</code></pre>
        </div>
    </div>

    <footer>
        <div class="container">
            <div class="row">
                <div class="col-sm-12 text-center">
                    footer
                </div>
            </div>
        </div>
    </footer>

</div>

CSS

html, body { height: 100%; }

body > .container {
    display: flex;
    flex-direction: column;
    height: 100%;
    width: 100%;                      /* override bootstrap styles */
    padding: 0;                       /* override bootstrap styles */
}

body > .container > .row {
    margin: 0;                        /* override bootstrap styles */
    display: flex;                    /* nested flex container */
    justify-content: center;          /* center content box on page */
}

body > .container > .row > .docs {
    width: 75%;                      /* adjust width of the content box here */
}

code {
    max-height: 200px;
    background-color: #eeeeee;
    word-break: normal !important;
    word-wrap: normal !important;
    white-space: pre !important;
}

footer {
    margin-top: auto;                /* stick footer to bottom of container */
    background-color: #CCC;
}

Revised Fiddle

Tested in Chrome and Firefox.

like image 20
Michael Benjamin Avatar answered Sep 29 '22 21:09

Michael Benjamin


What happens here is most definitely a bug in Chrome.

After playing around with your Fiddle, and looking at it with other browsers, I can conclude that this is a Chrome-specific problem. And a curious one.

For some reason, <div class="col-md-12 docs"> grows to the size it should have (the height of p and pre together), but doesn't account for the horizontal scrollbar inside the pre tag.

Here's an image to demonstrate the problem. The part with the red background is the container.

Chrome bug

Since pre has a border of 1px wide at the bottom, the result leaves a 1px gap for you to actually use the scrollbar. You can try it yourself. Just try to grab the most upper 1px line of the scrollbar.

Removing the flex properties does fix your problem, but we're not going to accept that.

Now, I would've thought that adding a padding of 0.1px to the bottom of the parent would fix the problem, but it didn't. I then tried wrapping the pre tag in a div with class chromefix, and then added the following CSS

.chromefix{
  overflow: hidden;
}

But that created an even weirder situation where the container grew with the scrollbar for about 50%

enter image description here

So I tried combining the two, but not a lot of difference there.

This is where I started looking at the pre tag and its properties. It has overflow: auto by Bootstrap default. So what I tried was adding

pre{
  overflow-x: scroll !important;
}

And guess what? It worked!

So all you have to do is add overflow-x: scroll !imporant to pre, and you're good to go! Here's a working Fiddle.

Hope this helps

As a sidenote. I think you want to move max-height: 200px to pre as well. It won't work when you've applied it to code.

like image 2
Gust van de Wal Avatar answered Sep 29 '22 21:09

Gust van de Wal


Problem seems to be with the width of <pre>.

When width of your screen goes below 768px no specific width is applied to the .container by bootstrap hence the issue is occurring.

When width of your screen is above 768px following classes from bootstrap.css come in picture.

@media (min-width: 1200px)
.container {
    width: 1170px;
}
@media (min-width: 992px)
.container {
    width: 970px;
}
@media (min-width: 768px)
.container {
    width: 750px;
}

As you can see once the width goes below 768px there is no specific width given.

To counter this issue, you have to write your css, something like this.

@media (min-width: 480px) {
 .container {
        width: calc(100% - 40px);
    }
}

Basically, you have to specify width for .container when screen width goes below 768px. Once you do, it will fix your issue.

like image 2
Aditya Ponkshe Avatar answered Sep 29 '22 21:09

Aditya Ponkshe