Targetting horizontal scrollbar with CSS
Asked Answered
H

4

3

macOS hides scrollbars for trackpad users, which results in my users not knowing they can scroll a result set horizontally. I'm trying to use CSS to target the horizontal scrollbars only, so that I can make them permanently visible.

I'm able to override both scrollbar visual behavior with CSS:

::-webkit-scrollbar{
    -webkit-appearance: none;
    width: 7px;
}
::-webkit-scrollbar-thumb{
    border-radius: 4px;
    background-color: rgba(0,0,0,.5);
    box-shadow: 0 0 1px rgba(255,255,255,.5);
}

https://jsfiddle.net/ypk62h8v/1/

But when I try to apply the :horizontal pseudo-element, it doesn't work (Mac/Chrome):

HTML:

<div class="frame" style="">
    <div style="width:500px;height:500px;">
    SCROLLABLE
    </div>
</div>

CSS:

.frame {
    overflow-y: auto;
    overflow-x: auto;
    border: 1px solid black;
    height: 3em;
    width: 10em;
    line-height: 1em;
}

::-webkit-scrollbar:horizontal {
    -webkit-appearance: none;
    width: 7px;
}
::-webkit-scrollbar-thumb:horizontal {
    border-radius: 4px;
    background-color: rgba(0,0,0,.5);
    box-shadow: 0 0 1px rgba(255,255,255,.5);
}

https://jsfiddle.net/ypk62h8v/

He answered 11/8, 2023 at 14:17 Comment(5)
You are required to post a minimal reproducible example here, within your question, and not a link to any other site.Republic
added reproducable exampleHe
If your goal is to make the scrollbars permanently visible, setting overflow: scroll instead of overflow: auto should accomplish that for you. Emphasis on should. I can't seem to get it to work on my MacBook with touchpad in any browser despite the docs here: developer.mozilla.org/en-US/docs/Web/CSS/overflow#scrollAcacia
this might help #46734799Carlson
The bounty probably attracted at least one ChatGPT plagiariser.Dose
D
1

You are very close to doing what you want. Unfortunately there's no native way that I'm aware of to achieve exactly what you want. In order to style either of the scrollbars, you need to override the DOM, and tell the browser that you want to use custom styles.

After doing that, you can target the :horizontal class directly.

If this was my project, and I had a lot of containers overflowing horizontally, I would create a special container class, something like .horizontal-container which would override the DOM, and apply the styles to make sure the horizontal scroll bar is visible. It's bad UX to be able to scroll on both the X and Y axis (Unless it's like a Figma canvas style interaction), so I wouldn't be too worried about the vertical scroll not being visible.

Additionally

You could add a subtle animation like my second snippet to single to users that there is additionally content to the right.

.frame {
  border: 1px solid black;
  height: 5em;
  width: 15em;
  line-height: 1em;
  
  overflow: auto;
}

p {
  margin: 0;
}

/* You first need to target all scrollbars to override the DOM */
::-webkit-scrollbar {
    -webkit-appearance: auto;
}

/* Then you can target the :horizontal class on it's own */
::-webkit-scrollbar-thumb:horizontal {
    border-radius: 20px;
    background-color: rgba(255,0,0,.5);
    box-shadow: 0 0 1px rgba(255,255,255,.5);
}
<div class="frame" style="">
  <div style="width:500px;height:500px;">
    <p>SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, 
    </p> 
  </div>
</div>

Animation

This is more dramatic than what I'd actually do, but it's an example.

.frame {
  overflow-y: auto;
  overflow-x: auto;
  border: 1px solid black;
  height: 7em;
  width: 15em;
  line-height: 1em;
  position: relative;
}

.frame::after {
  content: "";
  height: 100%;
  width: 4rem;
  position: absolute;
  /* Turn this on to see the animation more clearly 
    background: red;
  */
  background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%);
  top: 0;
  left: calc(100% - 2rem);
  animation: bounce 4s infinite ease-in-out;
}

@keyframes bounce {
  0% {
    transform: translateX(-2rem);
  }
  50% {
    transform: translateX(2rem);
  }
    100% {
    transform: translateX(-2rem);
  }
}

p {
  margin: 0;
}
<div class="frame" style="">
  <div style="width:500px;height:500px;">
    <p>SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, SCROLLABLE, 
    </p> 
  </div>
</div>
Dump answered 21/8, 2023 at 13:3 Comment(0)
Z
0

There's no direct CSS selector like :horizontal that you can use to specifically target horizontal scrollbars for customization in the same way you can target scrollbars without specifying orientation.

So, if you want to achieve this you should use following CSS and JavaScript Code:

// Add a class to the frame when the content overflows horizontally
const frame = document.querySelector('.frame');
const content = document.querySelector('.content');

frame.addEventListener('scroll', () => {
    if (content.scrollWidth > frame.offsetWidth) {
        frame.classList.add('has-horizontal-scroll');
    } else {
        frame.classList.remove('has-horizontal-scroll');
    }
});
.frame {
    overflow-y: auto;
    overflow-x: auto;
    border: 1px solid black;
    height: 3em;
    width: 10em;
    line-height: 1em;
}

.frame::-webkit-scrollbar {
    width: 7px;
    height: 7px;
}

.frame::-webkit-scrollbar-thumb {
    border-radius: 4px;
    background-color: rgba(0, 0, 0, .5);
    box-shadow: 0 0 1px rgba(255, 255, 255, .5);
}

.frame::-webkit-scrollbar-thumb:vertical {
    background-color: rgba(0, 0, 0, .5); /* Adjust vertical scrollbar appearance */
}


.frame.has-horizontal-scroll::-webkit-scrollbar-thumb:horizontal {
    background-color: rgba(0, 0, 0, .5); /* Adjust horizontal scrollbar appearance */
}
<div class="frame" style="">
    <div class="content" style="width:500px;height:500px;">
        SCROLLABLE
    </div>
</div>
Zephaniah answered 15/8, 2023 at 18:10 Comment(1)
You could reserve space by adding scrollbar-gutter: stable; to your frame's css along with scrollbar-width and scrollbar-color. This would indicate to the user that there's a scrollbar.Shirtmaker
V
0

Your code is well set up and working properly You just removed the ':horizontal' and .frame classes in the overflow-y: auto-hidden change; So that all those devices work.

.frame {
    overflow-y: hidden; // change auto to hidden
}

::-webkit-scrollbar{
    -webkit-appearance: none;
    width: 7px;
}
::-webkit-scrollbar-thumb{
    border-radius: 4px;
    background-color: rgba(0,0,0,.5);
    box-shadow: 0 0 1px rgba(255,255,255,.5);
}
Vanatta answered 19/8, 2023 at 13:31 Comment(0)
F
-1

Use overflow: scroll instead of overflow: auto

Flimflam answered 18/8, 2023 at 8:46 Comment(1)
This makes no differenceHe

© 2022 - 2024 — McMap. All rights reserved.