The problem is shown here:
https://codepen.io/team/css-tricks/pen/yLLqqgP
This is the important part:
html {
scroll-snap-type: y mandatory;
}
section {
height: 100vh;
scroll-snap-align: start;
}
When setting height of section > 120, or similar this issue can get fixed, but this is a hack.
When I start scrolling, with a scroll wheel, then it always scrolls two sections, which makes the whole logic unusable.
I am using Chrome: 86.0.4240.183.
This codepen example is from: https://css-tricks.com/practical-css-scroll-snapping/ which is a very well known ressource for css examples.
This is a known bug in Chrome unfortunately, caused by using either html or a container with a background-color property for the scroll container. It only affects scroll wheels and not trackpads or touch scrolling on mobile. See this thread for a demonstration of the problem.
The simplest solution is to just use a nested container to hold the scroll, although, bizarrely, you may notice that the scroll-snap now has a small delay on it. This is the best that can be done with the current implementation:
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
html {
overflow: hidden;
}
.container {
height: 100vh;
width: 100%;
overflow: auto;
scroll-snap-type: y mandatory;
}
h1 {
width: 100%;
height: 100vh;
scroll-snap-align: start;
border: 2px solid black;
display: flex;
justify-content: center;
align-items: center;
}
<div class="container">
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
</div>
The problem is unfortunately compounded once you realise that 100vh is also non-static (read: extremely janky) on some mobile browsers due to the implementation of retracting UI, potentially leading to unstyled gaps as the html layer shows through before the container fills up the remaining space. I've spent hours wrestling with this issue this year and have yet to come up with a totally satisfactory solution, settling for media queries to reset back to html in most cases and targeting any edge cases with JS.
Here's one possible media query you could add for that:
#media (hover: none) and (pointer: coarse) {
html {
overflow: auto;
scroll-snap-type: y mandatory;
}
.container {
height: auto;
display: contents;
scroll-snap-type: unset;
}
}
Related
I am working on a scrollable card gallery of sorts.
For this I am using a CSS grid structure.
Something along the line of:
<div class="cs-wrapper">
<div class="cs-container">
<div id="card-1" class="cs-card-container">
<div class="cs-card">
</div>
</div>
<div id="card-2" class="cs-card-container">
<div class="cs-card">
</div>
</div>
...
</div>
</div>
Using the css
.cs-content {
height:100vh;
position: relative;
display: grid;
grid-template-columns: var(--cs-container-grid-gap) 1fr var(--cs-container-grid-gap);
grid-gap: var(--container-grid-gap);
z-index:10;
}
.cs-container {
display: grid;
position: relative;
grid-gap: 0vw;
grid-template-columns:repeat(auto-fill, 100vw);
grid-auto-flow: column;
grid-auto-columns: calc( 100% / var(--cs-cards-per-screen));
grid-template-rows: 1fr;
-webkit-overflow-scrolling: touch;
scroll-behavior: smooth;
overflow-scrolling: touch;
overflow-x: scroll;
scroll-snap-type: x mandatory;
}
.cs-container > div {
height: 100%;
width: 100%;
position: relative;
margin:0;
overflow: auto;
scroll-snap-align: start;
}
.cs-card-container {
height: 100%;
width: 100%;
position: relative;
margin:0;
overflow: auto;
}
Now the code works as intended, the cards are positioned right and the scroll works.
However the inertia/momentum scrolling on mobile tends to scroll a bit to fast, when scrolling on mobile you have to swipe very sensibly to get to the next card and not skip 1 or 2 cards (you have to be able to swipe trough multipe cards if you'd wish to, so a stop on each card isn't an option).
Now I am looking for a way to slow down the scroll speed so it becomes usable
I'd prefer a CSS only solution if possible. Things I have tried:
Playing around with
.cs-container {
perspective: 1px;
transform-style: preserve-3d;
}
.cs-container > div {
transform: translateZ(-1px) scale(2);
margin-top:-10px;
margin-left:-10px;
top:-10px;
}
this did seem to slow the scroll down a bit, however the scroll acted unpredictable and as the divs are now in the background and scroll half as fast. as soon as cs-container has scrolled to the end only half the cards have been scrolled through (also the scroll snapp is now off by half a card)
Javascript
I tried a couple javascript solutions I found, but all of them relied on the scrolling being done with the mousewheel, so for mobile this didn't work
Did not run the code myself, but it sounds like you are looking for the property called:
{scroll-snap-stop: always}
You can use {scroll-behavior: smooth;} to the element for a smoother scroll.
Remember : When this property is specified on the root element, it applies to the viewport instead. This property specified on the body element will not propagate to the viewport.
There is a property: -webkit-overflow-scrolling: auto.
The value auto should disable momentum-based scrolling. This means that the content stops scrolling immediately when you remove your finger from the touchscreen.
Note: Unfortunately, this property is currently supported by only a few browsers. Instead you could also use the overflow:hidden propery on the .cs-wrapper element, and to get back the normal scrolling behavior, you can position a <div> absolutely inside of the element to get scrolling back with overflow:auto. I think this is the best option using only css!
I'm attempting to create a "bookshelf" using html and sass (Note: this is heavily based on http://ameijer.nl/2013/03/bookshelf-css-only/) You can see my version of the concept here:
https://mainstringargs.github.io/bookshelf.html
I'm trying to only show the horizontal scrollbar when necessary for the particular "bookshelf" -- for example, in the "Read" shelf above -- but not have it appear when not necessary -- see "Reading" & "On Deck" at the link.
I expected using "overflow: auto;" would give me this effect, but that seems to cause the scrollbar to always appear.
The relevant sass file is here: https://github.com/mainstringargs/mainstringargs.github.io/blob/master/src/styles/_bookshelf.scss
How can I only show the horizontal scrollbar when needed for each particular bookshelf?
As an example, it currently looks like this with horizontal scrollbars on both displayed bookshelfs even when not enough books:
I want it to look like this mockup (Note the bottom bookshelf has no horizontal scrollbar because there aren't enough books there, but the top one does because there are enough books to scroll):
You can use flexbox and let .books overflow vs .shelf just be sure to remove the width: 1470px; from .books, .shelf:after:
.shelf {
height:auto;
overflow: hidden;
padding: 0;
}
.books {
position: relative;
white-space: nowrap;
display: flex;
flex-wrap: nowrap;
overflow: auto;
align-items:flex-start;
justify-content: flex-start;
height: 420px;
z-index: 1;
}
.books, .shelf:after {
/* width: 1470px; */
box-sizing: border-box;
padding: 40px 30px;
margin: 0;
width: 100%;
}
.book {
flex-shrink: 0;
}
By looking at your code if you only want to apply a horizontal scroll when necessary and not vertically.
Use the following on your class name:
.books {
overflow-x: auto; // Auto horizontal
overflow-y: hidden; // Disable vertical scrolling
}
Try that see if it works. No need to add scroll but let the browser decide with the "auto" set.
After creating some basic messy sites I motivated myself to do something better and responsive. And I've got a problem.
The problem is when my site has more height than 100vh and I need to scroll it down, then appeares horizontal scroll.
I tried changing units on containers, removing left/right paddings, margins in some places added margin:0; padding:0; in my 'reset.css' file and still I have no idea what can I do to fix it.
I know that I can use overflow but I read that actually it's not fixing but hacking and I want to know why this happens.
My site looks kinda like this. Not exacly but kinda, and as you see there is little space to slide horizontaly.
Sample code :
.container{
display: flex;
flex-direction: column;
width:100vw;
https://codepen.io/anon/pen/zXLMPX
Also I'll be happy if u give me some advices/tips what I can do better in future, thank you!
The problem is coming from the fact that you haven't normalized your HTML yet. HTML naturally has some padding and margin. You should almost always remove this with the universal selector at the beginning of a project. You can also remove it from the html or body tags directly.
Here is a snippet without removing the default margin/padding:
.container {
display: flex;
flex-direction: column;
width: 100vw;
height: 100vh;
background-color: orange;
}
<div class="container"></div>
Here is a snippet removing the margin/padding using the universal selector:
* {
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: column;
width: 100vw;
height: 100vh;
background-color: orange;
}
<div class="container"></div>
If you remove the margin on your body tag it should remove the horizontal scroll:
body {
margin: 0;
}
Alternatively you can use overflow-x: hidden to always hide the horizontal scroll.
On your container use
.container { width: 100%; }
the issue might also be with how codepen displays your page.
If you want to disable horizontal scroll entirely you can always do this
body { overflow-x: hidden; }
I want to create a page with a main area and a scrollable side area. When the page is too small, I want the side area to wrap below and the whole page to scroll instead. If possible I want to do this in pure CSS. I've come up with the following, which works in Chrome but not Safari. (In Safari, the whole page always scrolls.)
How do I fix this, and more importantly, have I misunderstood flexboxes somehow?
html, body, main {
height: 100%;
margin: 0;
}
main {
display: flex;
flex-flow: row wrap;
overflow: scroll;
}
content {
min-width: 600px;
flex: 9999 1 auto;
background-color: #ffa;
}
aside {
flex: 1 1 auto;
overflow: scroll;
background-color: #aff;
}
<main>
<content>
main
</content>
<aside>
side
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10000<br>
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10000<br>
</aside>
</main>
View full page to see responsive behavior, or see this fiddle.
I've run into a very annoying issue only on iOS Safari 9+ (8.4 is fine) where, once the user quickly scrolls a page resulting in anchor links within fixed elements no longer being clickable due to the appearance and actual click/hit area not lining up with its element until the user scrolls again.
It doesn't happen the same way every time, and can take a few tries to "break" the system. Content must be longer than the viewport for this to work.
No workarounds to the problem yet. How can I solve this issue?
UPDATE: After further testing, the issue only happens with iOS Safari 9 and above, tested on iOS 8 and there is no problem.
UPDATE 2: It's now clear that this happens on most websites using position:fixed; and even position:-webkit-sticky;. You may want to check yours :)
HTML
<section>
<article></article>
<article></article>
<article></article>
</section>
<div class="sticky">
</div>
CSS:
html, body {
margin:0;
}
article {
display: block;
height: 200px;
width: 100%;
margin-bottom: 20px;
background: whitesmoke;
}
.sticky {
width:100%;
height:100px;
position: fixed;
bottom:0;
background: orange;
text-align:center;
}
.sticky a {
display: inline-block;
width: 100px;
height: 100px;
background: yellow;
}
http://codepen.io/toobulo/pen/dGEodo
The issue doesn't happen within Codepen editor, as it's related to mobile Safari's elastic / toolbar size changes. Please export code into own page, or use the following link:
https://cdn.rawgit.com/anonymous/3234ad797dd80e5f8905/raw/ab51c4d8621cfb827f83a33d21940579f8682cde/index.html
This problem is related to the bounce effect in ios and losing the toolbar & the header bar. The only way that i have found to fix this is to do the following:
html,
body {
height: 100%;
width: 100%;
overflow: auto;
-webkit-overflow-scrolling: auto
}
You could do it on a breakpoint as well so it only works for mobile. Hope this helps.
** Added the overflow scrolling.
I found that andy jones's answer effectively fixed this problem for me, but it had an unwelcome side effect: momentum scrolling no longer worked. This made scrolling down long pages on an iPad take forever.
Combining andy's answer with this tidbit from CSS tricks made my links clickable while also allowing for momentum scrolling:
html,
body {
height: 100%;
overflow-y: scroll; /* must be scroll, not auto */
-webkit-overflow-scrolling: touch;
}
I also found that the width: 100% style from andy's answer was unnecessary, so I removed that as well.
You can make .sticky a link absolute and apply following CSS so the link will be independent to the window/browser.
.sticky {
width: 50px;
}
.sticky a {
position: absolute;
top: 0;
bottom: 0;
margin: auto;
}