17

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?

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Josh Stone
  • 4,328
  • 7
  • 29
  • 37
  • 1
    In the future, please include your code in the question itself. Including a link to JSFiddle without doing so is against the rules. – TylerH Feb 10 '16 at 03:12
  • @TylerH, it's possible OP didn't include snippet for the same reason I removed it from my answer: It doesn't work. Although code works in fiddle demo, it breaks in SO snippet and doesn't reproduce the problem (or the solution I propose). – Michael Benjamin Feb 10 '16 at 03:25
  • @Michael_B The code works the same in the Stack Snippet for me as it does in JSFiddle, and reproduces the problem. What browser are you using? Either way, the code still needs to be in the question; having it in a Stack Snippet is just extra. – TylerH Feb 10 '16 at 03:29
  • @TylerH, Chrome 47, 48 and FF. Fiddle rendering scrollbar on content box. SO snippet rendering one long line; no scroll. Definitely a difference here. I had to remove SO snippet from my answer as a result. – Michael Benjamin Feb 10 '16 at 03:39
  • @Michael_B The JSFiddle and the Stack Snippet work identically for me in Firefox `44.0.1` and Chrome `48.0.2564.103 m` and Chrome Version `48.0.2564.109 m`. As you narrow the window, the code window loses its scrollbar and overflows the viewport, giving the browser window a horizontal scrollbar. This is the exact behavior Josh describes. I'm not sure what to tell you. – TylerH Feb 10 '16 at 03:44
  • @TylerH, not sure the cause. Regardless, you're right about the code. Needs to be included in the question. The demos are optional. – Michael Benjamin Feb 10 '16 at 03:45

5 Answers5

7

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/

Jörn Berkefeld
  • 2,540
  • 20
  • 31
  • I tried your `.container { width: 100%; }` in Chrome & FF and it works fine. Scrollbar is accessible. I don't see the need for `max-width` and `position: relative`. Looks like the first two lines of your answer are all that is needed. – Michael Benjamin Feb 16 '16 at 14:17
  • 1
    @Michael_B You won't see the problem if you just edit his fiddle and rerun it. Chrome apparently caches the working version. If you update the fiddle, do a hard refresh, and then try to use the scrollbar, you'll see why he added the `position: relative`. Or you can just look at [this one](http://jsfiddle.net/nturor46/38/). – DoctorDestructo Feb 16 '16 at 17:51
2

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.

Gust van de Wal
  • 5,211
  • 1
  • 24
  • 48
  • Should work if you add `width: 100%` to `.container`. Might also want to add `display: flex` to `.row` since the O.P. said in [comments](http://stackoverflow.com/a/35196624/2759272) that he plans to add a sidebar. – DoctorDestructo Feb 16 '16 at 17:38
  • @JörnBerkefeld What browser are you using? It's working for me – Gust van de Wal Feb 16 '16 at 18:11
  • @GustvandeWal try narrowing the width of the output frame in your fiddle and you'll see the problem – DoctorDestructo Feb 16 '16 at 18:24
  • @DoctorDestructo That is Bootstrap's media-query... That has nothing to do with my solution to the actual problem – Gust van de Wal Feb 17 '16 at 14:56
  • 1
    @GustvandeWal From the OP: "note that horizontal scrollbars for the code go away as you narrow the window". Well, ok, you got me. Your solution does indeed make the scrollbar not go away. Should teach him to make his questions more specific, if nothing else. – DoctorDestructo Feb 17 '16 at 21:50
  • gotta love the Doctor's sarcasm... :D (sorry Gust) – Jörn Berkefeld Feb 18 '16 at 09:05
2

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.

Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • this overwrites the (bootstrap) design – Jörn Berkefeld Feb 16 '16 at 14:00
  • @JörnBerkefeld, my friend, your answer overrides bootstrap, as well. Shouldn't a div be `width: 100%` by default? (Not that yours isn't a good answer.) – Michael Benjamin Feb 16 '16 at 14:12
  • it actually does not overwrite bootstrap rules because neither max-width nor position is defined for these layers (second & final approach in my answer). I think we agree that this seems to be a weird browser behavior. My approach reminds the browser of what "should be default" ;-) – Jörn Berkefeld Feb 17 '16 at 08:53
2

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.

Aditya Ponkshe
  • 3,840
  • 4
  • 39
  • 58
  • I like this answer because it just extends the current behavior instead of trying to change it. Still fails with really narrow widths, though, but I'm sure you could fix that by adding a few more min-widths. It also suffers from the Chrome bug mentioned [here](http://stackoverflow.com/a/35397304/2759272) and [here](http://stackoverflow.com/a/35305829/2759272) (also fixable). – DoctorDestructo Feb 16 '16 at 18:25
  • @DoctorDestructo One can fix issue of really narrow widths simply by editing the media query. I didn't handle the possibility below 480px because really, where would you face such situation? – Aditya Ponkshe Feb 17 '16 at 11:36
  • 1
    I can certainly narrow my browser window to less than 480px. – DoctorDestructo Feb 17 '16 at 22:07
1

Wrap the prev tag and its content with div like below.

<div class="code">{your code goes here}</div>

css :

.code{
     width:92vw; /*you can change this in media query to specific device width for better results*/
     overflow-x:auto;
}

Working jsfiddle link

Shiva
  • 728
  • 5
  • 13
  • Using `width:92vw` doesn't quite work because the size of the `code` box doesn't match up with the rest of my content as the page is scaled. – Josh Stone Feb 04 '16 at 18:32
  • Here's a fiddle with a sidebar. I'm not sure how to get the `code` box sized just right so that it doesn't bleed over to the sidebar as the page is resized. http://jsfiddle.net/jhalterman/nturor46/9/ – Josh Stone Feb 04 '16 at 18:59