Android Stock Browser Not Respecting CSS Overflow
Asked Answered
C

2

16

I'm working with a client who would like part of their interface to have a somewhat customized method of scrolling. They don't want the usual scrollbars to be visible; they want desktop / laptop users to scroll with their mouse wheel / touchpad and they want mobile users to scroll with their finger. They also want graphics of an up arrow and a down arrow to provide an alternate method of scrolling and also to make it obvious to the user that scrolling is possible (since the actual scrollbars are hidden). The client is set on this method of scrolling.

I put together some code that works on all device / browser combinations that I've tried it on except for Android's stock browser. I have confirmed this issue with the following configurations:

  • Android 4.1.2 (emulator)
  • Android 4.2.2 (actual device)
  • Android 4.2.2 (emulator)
  • Android 4.3 (emulator)

This issue is not present on Android 4.4.2 (emulator), though.

In order to keep things simple for this question, I'm not including the graphics of the up and down arrows and the accompanying logic.

Here's the code (jsFiddle demo):

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Demo</title>
    <style>
      #side_nav, .category {
        position: absolute;
      }

      #side_nav {
        -webkit-user-select: none;
      }

      .category {
        display: none; /* Will be shown when user clicks on an option */
        top: 0;
        left: 150px;
      }

      .ul_wrapper, .ul_wrapper ul {
        width: 125px;
        height: 242px;
      }

      .ul_wrapper {
        background: #ccc;
        border: 3px solid #000;
        border-radius: 6px;
        text-align: center;
        overflow: hidden;
      }

      ul {
        margin: 0;
        padding: 0;
        list-style: none;
        overflow-y: scroll;
      }

      li {
        padding-top: 10px;
      }

      li:last-child {
        padding-bottom: 10px;
      }

      span {
        display: inline-block;
        width: 100px;
        height: 100px;
        border: 3px solid #999;
        border-radius: 6px;
        cursor: pointer;
      }

      #chosen_option {
        float: left;
        margin-left: 150px;
      }
    </style>
  </head>
  <body>
    <div id="side_nav">
      <div class="ul_wrapper">
        <ul>
          <li>
            <span>Option 1</span>
            <div class="category">
              <div class="ul_wrapper">
                <ul>
                  <li><span>Option 1a</span></li>
                  <li><span>Option 1b</span></li>
                  <li><span>Option 1c</span></li>
                </ul>
              </div>
            </div>
          </li>
          <li>
            <span>Option 2</span>
            <div class="category">
              <div class="ul_wrapper">
                <ul>
                  <li><span>Option 2a</span></li>
                  <li><span>Option 2b</span></li>
                </ul>
              </div>
            </div>
          </li>
          <li>
            <span>Option 3</span>
            <div class="category">
              <div class="ul_wrapper">
                <ul>
                  <li><span>Option 3a</span></li>
                </ul>
              </div>
            </div>
          </li>
        </ul>
      </div>
    </div>

    <div id="chosen_option"></div>

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script>
      function get_scrollbar_width() {
        var div, body, W = window.browserScrollbarWidth;
        if (W === undefined) {
          body = document.body, div = document.createElement('div');
          div.innerHTML = '<div style="width: 50px; height: 50px; position: absolute; left: -100px; top: -100px; overflow: auto;"><div style="width: 1px; height: 100px;"></div></div>';
          div = div.firstChild;
          body.appendChild(div);
          W = window.browserScrollbarWidth = div.offsetWidth - div.clientWidth;
          body.removeChild(div);
        }
        return W;
      }

      var scrollbar_width = get_scrollbar_width();

      $('#side_nav ul').css({
        'padding-right': scrollbar_width,
        'margin-left': scrollbar_width / 2
      });

      $('span').on('click', function(event) {
        event.stopPropagation(); // Prevent $('html').click(); from triggering

        var parent_li = $(this).parent();
        var child_category = parent_li.children('.category');

        if (child_category.length) {
          var show_div = false;

          if (child_category.is(':hidden')) {
            show_div = true;
          }

          parent_li.siblings().find('.category:visible').fadeOut();

          if (show_div) {
            child_category.fadeIn();
          }
          else {
            parent_li.find('.category:visible').fadeOut();
          }
        }
        else {
          $('#chosen_option').html('You chose ' + $(this).html().toLowerCase());
          $('.category:visible').fadeOut();
        }
      });

      $('html').click(function() {
        $('.category:visible').fadeOut();
      });
    </script>
  </body>
</html>

When you tap on any of the three options, a second list of options should appear to the right. However, it never appears on Android's stock browser unless you remove overflow-y: scroll; from the ul CSS rules, but then you can no longer scroll.

The problem is best illustrated by replacing left: 150px; with left: 25px; in the .category CSS rules. When I do that, this is what it looks like in a working browser:

Working browser

And this is what it looks like in Android's stock browser:

Android's stock browser

One other thing I should note is that it works in Chrome for Android.

Is there a way that I can make this work in Android's stock browser?

Chiropractic answered 24/1, 2014 at 22:56 Comment(4)
Try adding z-index:10; to .category in order to bring it forward.Felker
@Felker That did not fix the problem. Thank you, though.Chiropractic
@nick it's been a while, how did you solve it?Arthur
@KilianSchefer I ended up removing all the nesting and wrote JavaScript to show or hide the appropriate things. I don't like relying on JavaScript, but with this particular website, JavaScript is most definitely required anyway.Chiropractic
A
2

I've had issues with the stock Gingerbread Android browser. It does not handle the overflow CSS property well at all. In order to enable scrolling on this browser I had to apply the overflow ("scroll" or "auto") to the BODY container only.

Aplite answered 29/1, 2014 at 16:40 Comment(1)
Thanks for the information. In my case, I'm only concerned with Android 4.0 and higher, which I believe covers over 75% of Android users.Chiropractic
V
0

I believe Android stock browser doesn't support x/y-specific overflow properties. Instead of turning on overflow-y, turn on overflow then turn it off for overflow-x. Example:

ul {
    margin: 0;
    padding: 0;
    list-style: none;
    overflow-y: scroll;
}

should become:

ul {
    margin: 0;
    padding: 0;
    list-style: none;
    overflow: scroll;
    overflow-x: visible;
}

Generally I use auto instead of scroll so the scroll bars won't show up if not necessary. Also, perhaps overflow-x: hidden; may be more desirable in your situation. Basically this will apply your desired overflow-y property to overflow-x as well, but usually this is more desirable than the rule being ignored completely. For browsers that support the axis-specific overflows the user won't know the difference.

Vicarial answered 29/1, 2014 at 16:38 Comment(2)
Sadly, this didn't work. I think it has something to do with the behavior explained here. Also, Android's stock browser appears to support x/y-specific overflow properties just fine (I tested this page and this page using Android 4.2.2's stock browser). Lastly, to explain why I have overflow-y: scroll; in the ul CSS rules, setting it to auto causes the option 2 and 3 choices to not be centered. Thanks for the attempt!Chiropractic
I'm glad you found more info on the issue although there doesn't seem to be a solution in that post. What I posted is specifically relevant to IE8 and has worked for me quite often, was hoping it could be relevant in Android stock as well.Vicarial

© 2022 - 2024 — McMap. All rights reserved.