3

The Rant

So I spent over an hour on a pure css drop down and close menu which I thought was pretty slick, then only after doing all the styling and making it look good with my site did I decide to check it in Chrome. Oops.

The Question(s)

Why does my pure css dropdown menu make Google's Chrome scroll the page down when the button is clicked? Is there an easy way to make it compatible for both FF and Chrome?

The Hint

It has something to do with the menu being a position: fixed header but I don't know why Firefox behaves as I wanted while Chrome pulls an IE.

The Example

Here's a stripped down to bare bones example on jsfiddle

http://jsfiddle.net/Hastig/a77ewh89/

  • view in chrome versus firefox to see the difference
  • click on menu1, menu2 or menu3 to activate dropdown
  • menu close button code not included as it makes no difference

The Clues

  • It's something about Chromes handling of position: fixed;
  • Variations of the slide effect using either margin or height bug chrome the same way.
  • On the full site-ready version I have a click to close button which works perfectly in both FF and Chrome, it scrolls the menu back up. When the close button is clicked in Chrome the scroll bug does not reverse the page scroll.
  • Also on the full version I have hover styling added to the buttons. Once a dropdown menu is opened, in Chrome, hovering over those buttons makes the page scroll down as well.
  • The scrolling problem ends once the page bottom is reached.

The Code

css

.header {
    position: fixed;    top: 20px;
    background-color: rgba(0,0,0,0.8);
}

.button {
    color: white;
    display: inline-block;
}

.menu {
    width: 500px; height: 0px;
    overflow: hidden;
    transition: all 1s;
    color: white;
}

#menu1:target, #menu2:target, #menu3:target {
    height: 300px;
}

.content {
    margin: 80px 0px 0px 0px;
    width: 500px;
    background-color: red;
}

.filler-divs {
    font-size: 40px;
    color: white;
}

html

<div class="header">
    <a class="button" id="button1" href="#menu1">Menu 1</a>
    <a class="button" id="button1" href="#menu2">Menu 2</a>
    <a class="button" id="button1" href="#menu3">Menu 3</a>

    <div class="menu" id="menu1">menu 1</div>
    <div class="menu" id="menu2">menu 2</div>
    <div class="menu" id="menu3">menu 3</div>
</div><!-- end header -->

<div class="content">
    <div class="filler-divs">filler filler filler filler filler filler filler filler filler filler</div>
    <div class="filler-divs">filler filler filler filler filler filler filler filler filler filler</div>
<!-- add lots more of these divs to fill the page with text so you can see it scroll down - scrolling stops at page bottom -->  
</div><!-- end content -->
2
  • hm looks like you'd need javascript to counteract the webkit behavior. - which negates your goal to use pure css - Commented Apr 11, 2015 at 23:54
  • I should probably just end my pure css crusade and start learning some more javascript Commented Apr 13, 2015 at 1:32

1 Answer 1

3

Abandoning your pure CSS approach is not necessary. See my example below. The solution is achieved by placing all your content in a container element that replicates your body element, but which Chrome won't scroll through in an attempt to display the menu element.

New version: http://jsfiddle.net/scarl3tt/dm89g0m5/

A div.fake-body must wrap your .content class:

.fake-body {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    padding: 10px;
    overflow-y: auto;
}

...and your .header needs to either move after this in the DOM or be marked with z-index: 1 to ensure that it displays above the fake body and is able to be interacted with.

Sign up to request clarification or add additional context in comments.

4 Comments

Note: I just updated this so it actually implements the changes I described. I never really use jsfiddle, and I forgot to click update, so the version that was linked for 3 minutes didn't actually have any changes from yours. Sorry if you looked at it in that time and were disappointed.
That's perfect, I'm going to be using that technique a lot in the future. Thanks so much! P.S. I wasn't online during those three minutes :)
One thing I didn't notice because the fiddle I made isn't centered is the scrollbar added by .fake-body kicks the content area to the left so that the header isn't centered in relation to the content in .fake-body. To compensate I added a -8px margin-left on .header.
The scrollbar issue is one that unfortunately cannot be solved with pure CSS. I'm working on a large-scale Angular app at the moment and have to use JS to detect the browser's scrollbar width and compensate. It's not too big a deal when it's Chrome vs Firefox vs IE, because they're all within a few pixels of eachother, but on mobile browsers and Safari, scrollbars are often entirely non-present, or appear over content rather than beside it. It's pretty unfortunate :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.