scroll behaviour smooth not working at all - html

I am wondering why my scroll smooth isn't working at all. I am not too sure why? I thought adding overflow-y: scroll; scroll-behavior: smooth; will help but its not working. Here is my code:
#container{
overflow-y: scroll;
scroll-behavior: smooth;
}
.topTab{
bottom: 0;
position: fixed;
font-size: 25px;
color: white;
}
.pg{
font-size: 100px;
height: 100vh;
background-color: blue;
text-align: center;
}
a{
color: white;
}
<div class = "topTab">
<li>1</li>
<li>2</li>
<li>3</li>
</div>
<div id = "container">
<div id = "1" class= "pg">1</div>
<div id = "2" class = "pg">2</div>
<div id = "3" class = "pg">3</div>
</div>

I was facing the same issue in modern Chrome (e.g. in version 88.0.4324.182) but I then enable the smooth scrolling flag using the below-mentioned URL :
chrome://flags/#smooth-scrolling

you have to override the current auto scroll settings by putting !important into your css code.
*, html {
scroll-behavior: smooth !important;
}
```

Try this one...
html {
scroll-behavior: smooth;
}
#container{
overflow-y: scroll;
}
.topTab{
bottom: 0;
position: fixed;
font-size: 25px;
color: white;
}
.pg{
font-size: 100px;
height: 100vh;
background-color: blue;
text-align: center;
}
a{
color: white;
}
<div class = "topTab">
<li>1</li>
<li>2</li>
<li>3</li>
</div>
<div id = "container">
<div id = "1" class= "pg">1</div>
<div id = "2" class = "pg">2</div>
<div id = "3" class = "pg">3</div>
</div>

If adding scroll-behavior:smooth to html is not working, what worked for me is adding it to the body as well.
html, body {
scroll-behavior: smooth
}

In my case, it wasn't working because of my windows setting for best performance where I had disabled all animations. Turning it off did the required work
[Type Adjust the appearance and performance of Windows in the start menu to get this dialog box and enable all]

First ensure if your browser is compatible with the scroll-behavior or not.
Check browser compatibility with scroll-behavior
If your browser is compatible with this property but still smooth scroll is not working
then this is not fault or error in code but you have to change a small setting of your browser.
If you are on chrome browser go to URL "chrome://flags/" depending upon your browser and press ctrl+f to open find dialogue-box and search for smooth scrolling and simply enable it and re-launch browser to make changes.

in case anyone has problems with this with Vue:
Adding
<style>
html {
scroll-behavior: smooth;
}
</style>
to App.vue
worked for me!

I solved my problem with chrome by using this:
html:focus-within {
scroll-behavior: smooth;
}
More on the subject is posted on Css-tricks "Fixing Smooth Scrolling with Find-on-Page"

Unfortunatelly this will also stop working if your device "prefers-reduced-motion"...
I always thought overwriting stuff that's not "auto" by nature, is bad practice, but this seems to be a thing now.

While reading some of the answers got an idea to check if windows performance settings could be somehow related, and after switching to "adjust for best appearance" in System Properties > Performance Options scrolling became smooth.

I made a custom solution with the easeOutSine function:
function scrollTop (initial?: number) {
if (document.documentElement && document.documentElement.scrollTop && document.documentElement.scrollTop > 10) {
if (typeof initial === 'undefined') initial = document.documentElement.scrollTop;
const progress = (initial - document.documentElement.scrollTop + 1)/initial;
document.documentElement.scrollTo({top: initial*(1-easeOutSine(progress))});
setTimeout(() => {
scrollTop(initial);
}, 10);
}
}
function easeOutSine(x: number): number {
return Math.sin((x * Math.PI) / 2);
}
since smooth isn't stable on my tests and I can't depend on the user enabling a flag.
You can tune the speed by changing the setTimeout's second argument.

Paste the below link in your browser which you are going to use as the live server:
chrome://flags/#smooth-scrolling
Then, a new tab will open up and then you can enable the smooth scrolling option and relaunch the tab. For putting the smooth scrolling action into your website, you have to put the below code in your code editor:
<html lang="en" style="scroll-behavior: smooth;" >

Just a little thing to check... I had the same issue but eventually realised / realized that I was spelling 'behaviour' the English way and not the American-English way. scroll-behavior: smooth; should work on the html selector if correctly spelled. Though I appreciate that this was not the case for #James_Lee.

I tried all the solutions but got nowhere.
Biggest steps I took to fix it in my system were:
Restarting my frontend client.
Putting overflow-y: "auto"
Placing scroll-behavior : smooth in html outside container was not generating the desired result so I put it back inside the container and now it works
Note: I did these CSS changes for the parent container while doing same in the actual container also didn't help me.
#container{
overflow-y: auto;
scroll-behavior: smooth;
}

My problem was really simple, but maybe someone else is making the same mistake, hence this answer.
For me I had changed my anchor links from
<a href="#Home">
to
<a href="index.html#Home">
The anchor links behavior was indeed smooth scrolling within my IDE's server's preview browser as well as locally in my browsers.
However, once I published to Cloudflare Pages the smooth scrolling changed to jumping.
I changed the anchor link back to
<a href="#Home">,
which brought smooth scrolling back to my staging site on Cloudflare Pages.

Related

Scroll Snap Bug (Chrome on Mac) - allowing scroll up into the HTML void

Trying to work out if this is a bug with Chrome or with my code. With the below code, when I scroll down it does what I want it to, but when I scroll up it lets me scroll as high as I want without the body snapping back. I've applied the scroll snapping to html because it does not work in Chrome if on body.
Demo: http://manifest.thedevtest.com/scrollsnap/ (scroll up)
Code:
<html>
<head>
<title>Chrome Scroll Snap Issue Demo</title>
<style>
* {
margin: 0;
padding: 0;
}
html {
scroll-snap-type: mandatory;
scroll-snap-points-y: repeat(100vh);
scroll-snap-type: y mandatory;
background: red;
}
section {
height: 100vh;
width: 100vw;
scroll-snap-align: start;
}
.foo {
background-color: green;
}
.bar {
background-color: blue;
}
</style>
</head>
<body>
<section class="foo">
</section>
<section class="bar">
</section>
</body>
</html>
Can you guys replicate this, and if so, do you have any thoughts on preventing it?
I still haven't ascertained whether this is a bug with chrome or not, but the fix is to manage the overscroll behaviour (which can be done in Chrome) https://developers.google.com/web/updates/2017/11/overscroll-behavior
body {
overscroll-behavior-y: none;
}
Does the job. With thanks to /u/Anemina on reddit. https://old.reddit.com/r/css/comments/i9kkiw/scroll_snap_bug_chrome_on_mac/
Looks like someone logged a bug already for the HTML continued overflow bug. I've seen 1 other issue like this too, where you could keep scrolling up, where scroll-snap-points weren't used. So I don't think they're the issue.
I was able to put scroll-snap-type on body, which fixed the demo for me. Chrome 87.
body {
scroll-snap-type: y mandatory;
}
Try again?
My 2 cents / thoughts:
I don't think it's a good idea to put scroll snap on the html tag. I usually end up extracting my body scroll-snap prototypes into a <main> or something, and make it more of a component than a document style.

How to append a HTML markup via Chrome Extension without leaking styles of the host page to the appended element? [duplicate]

I wrote a Google Chrome extension, which popups a dialog with an autocomplete field and it's own style, but there are some sites where my CSS gets totally broken, which doesn't look very nice.
I know about isolating styles with iFrames, but in Google Chrome extension there is no way to isolate my HTML and CSS in this way. Another method is to wrap all my stuff into a separated div with it's own id and relative styles for that id, and I do so, but it seems that it doesn't work on some sites with "hard" tags style overloading or "!important" directives in the CSS code.
So, I want to know is there any way to really isolate my styles in z convenient way or it's my bad carma to overload every little CSS property to fix one or another style issue for each site?
By the way: I set up my manifest to load all the things at the "document_end", but I see it's not being applied to the stylesheets which is every time loaded whenever the DOM is ready.
At the time of asking the question, your only option was to either use iframes, or stylesheets with a very high specificity and explicitly set all properties that might affect styles. The last method is very cumbersome, because there will always be some property that is overlooked by you. Consequently, the only usable method for isolating stylesheets was to use iframes.
The solution to this problem -isolation of styles without iframes- is Shadow DOM (since Chrome 25). You can find a tutorial at HTML5 Rocks. For a real-world Chrome extension that uses Shadow DOM to isolate styles, see Display #Anchors (source code here).
As I've recently gone through the gauntlet of this issue, I want to share some information I think is valuable.
First, Rob W's answer is correct. Shadow DOM is the correct solution to this problem. However, in my case not only did I need CSS isolation, I also needed JavaScript events. For example, what happens if the user clicks a button that lives within the isolated HTML? This gets really ugly with just Shadow DOM, but we have another Web Components technology, Custom Elements, to the rescue. Except that as of this writing there is a bug in chrome that prevents custom element in chrome extensions. See my questions here and here and the bug here.
So where does that leave us? I believe the best solution today is IFrames, which is what I went with. The article shahalpk linked is great but it only describes part of the process. Here's how I did it:
First, create an html file and js file for your isolated widget. Everything inside these files will run in an isolated environment in an iframe. Be sure to source your js file from the html file.
//iframe.js
var button = document.querySelector('.my-button');
button.addEventListener('click', function() {
// do useful things
});
//iframe.html
<style>
/* css */
</style>
<button class='my-button'>Hi there</button>
<script src='iframe.js'></script>
Next, inside your content script create an iframe element in javascript. You need to do it in javascript because you have to use chrome.extension.getURL in order to grab your iframe html file:
var iframe = document.createElement('iframe');
iframe.src = chrome.extension.getURL("iframe.html");
document.body.appendChild(iframe);
And that's it.
One thing to keep in mind: If you need to communicated between the iframe and the rest of the content script, you need to chrome.runtime.sendMessage() to the background page, and then chrome.tabs.sendMessage from the background page back to the tab. They can't communicate directly.
EDIT: I wrote a blog post detailing everything I learned through my process, including a complete example chrome extension and lots of links to different information:
https://apitman.com/3/#chrome-extension-content-script-stylesheet-isolation
In case my blog goes down, here's the sources to the original post:
Blog post
Example source
Either use all
.some-selector {
all: initial;
}
.some-selector * {
all: unset;
}
or use Shadow DOM
Library
function Widget(nodeName, appendTo){
this.outer = document.createElement(nodeName || 'DIV');
this.outer.className = 'extension-widget-' + chrome.runtime.id;
this.inner = this.outer.createShadowRoot();
(appendTo || document.body).appendChild(this.outer);
}
Widget.prototype.show = function(){
this.outer.style.display = 'block';
return this;
};
Widget.prototype.hide = function(){
this.outer.style.display = 'none';
return this;
};
Usage
var myWidget = new Widget();
myWidget.inner.innerHTML = '<h1>myWidget</h1>';
You can access the widget contents via myWidget.inner and the outer via myWidget.outer.
Styles
/*
* Reset Widget Wrapper Element
*/
.extension-widget-__MSG_##extension_id__ {
background: none;
border: none;
bottom: auto;
box-shadow: none;
color: black;
cursor: auto;
display: inline;
float: none;
font-family : "Helvetica Neue", "Helvetica", "Arial", sans-serif;
font-size: inherit;
font-style: normal;
font-variant: normal;
font-weight: normal;
height: auto;
left: auto;
letter-spacing: 0;
line-height: 100%;
margin: 0;
max-height: none;
max-width: none;
min-height: 0;
min-width: 0;
opacity: 1;
padding: 0;
position: static;
right: auto;
text-align: left;
text-decoration: none;
text-indent: 0;
text-shadow: none;
text-transform: none;
top: auto;
vertical-align: baseline;
white-space: normal;
width: auto;
z-index: 2147483648;
}
/*
* Add your own styles here
* but always prefix them with:
*
* .extension-widget-__MSG_##extension_id__
*
*/
.extension-widget-__MSG_##extension_id__{
position: fixed;
top: 100px;
margin: 0 auto;
left: 0;
right: 0;
width: 500px;
}
.extension-widget-__MSG_##extension_id__::shadow h1 {
display: block;
margin: 0 auto;
padding: 20px;
background-color: yellow;
border: 10px solid green;
font-size: 20px;
text-align: center;
}
I recently created Boundary, a CSS+JS library to solve problems just like this. Boundary creates elements that are completely separate from the existing webpage's CSS.
Take creating a dialog for example. After installing Boundary, you can do this in your content script
var dialog = Boundary.createBox("yourDialogID", "yourDialogClassName");
Boundary.loadBoxCSS("#yourDialogID", "style-for-elems-in-dialog.css");
Boundary.appendToBox(
"#yourDialogID",
"<button id='submit_button'>submit</button>"
);
Boundary.find("#submit_button").click(function() {
// some js after button is clicked.
});
Elements within #yourDialogID will not be affected by the existing webpage. And find() function returns a regular jQuery DOM element so you can do whatever you want with it.
Hope this helps. Please let me know if you have any question.
https://github.com/liviavinci/Boundary
Use iframes. It's a workaround, but works fine.
Maxime has written an article on it.

Issues with touch scroll on iOS when focusing inputs

I am having some issues with a scrollable div on iOS. When trying to scroll by touching outside an input, it scrolls ok without any problem but when I try to scroll and I touch an input to start scrolling (there are a lot of chances that it happens because it is a div with a lot of inputs) it scrolls the whole window instead scrolling the div. I don't have that problem either in desktop or Android. I found a similar question (iOS HTML Input Tag Stops Scrolling in Scrollable Element) but it doesn't have any answer either. While I don't find any good solution, I decided to prevent the event touchmove when the user touches an input, but it is not exactly what I want.
Maybe someone already faced this problem and can help. I would really appreciate it, thanks in advance.
To get native momentum scrolling on iOS 5+, you'll need:
div {
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
Source: Overflow
Maybe you also need:
div > * {
-webkit-transform: translateZ(0px);
}
Source: Similar question in Stack Overflow
Source 2: Another similar question
This stuff made me crazy too, after testing everything, I found the following answer from Thomas Bachem here working and made it simpler in jquery.
Just add a class scrollFix to the inputs and you are ready to go. (or directly apply that js to any inputs/textarea using$('input, textarea')
Now when you touch and scroll on an input on iOS 8+, the input get all its "pointer-events" disabled (including the problematic behavior). Those "pointer-events" are enabled when we detect a simple touch.
$('.scrollFix').css("pointer-events","none");
$('body').on('touchstart', function(e) {
$('.scrollFix').css("pointer-events","auto");
});
$('body').on('touchmove', function(e) {
$('.scrollFix').css("pointer-events","none");
});
$('body').on('touchend', function(e) {
setTimeout(function() {
$('.scrollFix').css("pointer-events", "none");
},0);
});
Hacky workaround, but by doing this I was able to make scrolling work even on form inputs. The JS forces a reflow in the rendering engine, which is where the bug in iOS8 Safari lies. Changing the height to auto also improved scrolling when focused on a form element, since scrolling is forcibly handled by the browser when focused.
Markup:
<div class="modal-backdrop-container">
<div class="modal-backdrop">
<div class="modal> <!-- Content --> </div>
</div>
</div>
CSS:
.modal-backdrop-container {
z-index: 10;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: 100%;
}
.modal-backdrop {
z-index: 10;
height: 100%;
background-color: rgba(255,255,255,0.5);
overflow: auto;
overflow-x: hidden;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.modal {
position: relative;
width: 400px;
max-width: 100%;
margin: auto;
background-color: white;
}
JS:
// reflow when changing input focus
$modalInputs = $('.modal').find(':input');
modalInputs.on('focus', function() {
var offsetHeight = modal.$backdrop[0].offsetHeight;
modal.$backdropContainer.css({
'height': 'auto'
});
});
modalInputs.on('blur', function() {
var offsetHeight = modal.$backdrop[0].offsetHeight;
modal.$backdropContainer.css({
'height': ''
});
});
Not sure of the var offsetHeight = modal.$backdrop[0].offsetHeight; line is needed, since both this and changing the height value should force a reflow.

PhoneGap/Cordova: Prevent horizontal scrolling

I have an app built on Cordova and on some of my pages I am able to scroll horizontally out of my content into white space.
This is weird as I have nothing there that extends beyond my #wrapper, which is set to width: 100%.
So I was wondering if there was a way I could disable horizontal scrolling in the app altogether?
UPDATE:
Code on page as requested:
body {
background-color: #fff;
font-family:Arial, Helvetica, sans-serif;
color: #b7b8b9;
height: 100%;
width: 100%;
}
iframe{
border: none;
width: 100%;
/*margin-top: 50px;*/
}
#header{
height: 50px;
width: 100%;
}
<body>
<div id="wrapper">
<div id="header">
<div class="headerback">Home</div>
<div class="headerrefresh"><script>var pathname = window.location.pathname;</script><script>document.write('Refresh')</script></div>
<div class="headertitle"><h2>Get the Look</h2></div>
</div><!--HEADER-->
<iframe src="http://www.mbff.com.au/getthelook"></iframe>
</div>
</body>
Try to debug your page in Chrome (webkit) with the exact dimensions of your device. This solves most rendering issues for me.
I do not know the specific issue here, but it looks like one of your elements is flowing outside of the wrapper. You could for example try this in your css:
div.wrapper { overflow: hidden; width: inherit; }
Although it might be a better idea to find out why your page is expanding horizontally?
I was looking for the solution to this problem for a long time.
Finally I solved it in the following way.
I set style for bodyand html tags:
position: fixed;
width: 100%;
height: 100%;
overflow: hidden;
After that I've added div to body and set the style for it:
overflow-y: auto;
height: 100%;
So, I have got fixed body, which contains div with vertical scroll bar.
// Phone Gap disable only horizontal scrolling in Android.
// Add this code in your Phone Gap Main Activity.Initially Declare the variable
private float m_downX;
//Then add this code after loadUrl
this.appView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
// save the x
m_downX = event.getX();
}
break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
// set x so that it doesn't move
event.setLocation(m_downX, event.getY());
}
break;
}
return false;
}
});
Try adding the following code to your .html file:
document.body.addEventListener('touchmove', function(event) {
event.preventDefault();
}, false);
For the sake of completeness, I thought the answer which makes use of the official method of doing such a thing via the preference tag should be added:
<preference name="DisallowOverscroll" value="true"/>
Supported by Android and iOS according the documentation.
Default: false
Set to true if you don't want the interface to display any feedback when users scroll past the beginning or end of content. On iOS, overscroll gestures cause content to bounce back to its original position. on Android, they produce a more subtle glowing effect along the top or bottom edge of the content.
In my case it was broken styling like below
<body>
<div style="margin-left:5%; width:100%">Content</div>
</body>
which cause div to became horizontally bigger than body. I could see scroll when app run in browser. Set width to 90% (as it was initially intended) fixed the problem.
Generally, as it already pointed out here, enough to find element with wrong style which makes your page expanding horizontally and fix it.
BTW DisallowOverscroll was not helpful in above case.

PNG image appears in IE8, disappears in IE7

I'm attempting to display a logo (PNG created in Paint.NET) on my web page (XHTML 1.0 Transitional), like this:
<body>
<div class="header">
<div class="logo">
<img src="logo.png" />
</div>
<!-- etc. -->
.header is styled as follows:
.header {
background-color: Black;
color: White;
margin-left: -3em;
padding-top: 12px;
padding-left: 2em;
padding-bottom: 12px;
font-size: 1.4em;
}
.header .logo {
float: right;
}
The logo is white-on-black, with some other colours.
On IE8 (and Google Chrome), the image is displayed correctly. On IE7, the image is not displayed at all. What am I doing wrong?
I don't care about IE6.
If you drag-drop the image directly into IE7 does it display correctly?
If it does, then the issue isn't with the image but it's with your HTML or the CSS.
I don't have IE7 here so can't test directly, but I can recommend a simple approach to troubleshooting:
Remove the CSS styles one-by-one until the image renders in all of your target browsers. That should tell you what is causing the issue (hopefully the reason why will then be relatively easy to fathom)
If it is the float:right that messes it up perheps you should try to clear your floats. Try setting overflow:hidden; on .header class, or apply clear:both on the element that follows it in the markup.
Also the img tag always requires the alt attribute - you can however leave it blank - alt=""
HTML or XHTML? Don't think that a self-closing img-tag is valid in HTML.
EDIT: You are also missing the alt-attribute.
I have this problem in an MVC.NET application using an IMG tag with a src=data string.
At the end of the day, I don't care what's causing it, since it's 1 image out of 60000 (and only in IE)
function showPicture() {
if ($('#picture').css("display") == "none") {
$('#picture').css("display", "");
clearInterval(interval);
}
}
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))
interval = setInterval(showPicture, 500);
While I think it's strange that only certain records cause the Display:None attribute to be applied inline, I'm comfortable with sharing this, since the CSS Display:None is not coming from my code.
At any rate, theoretically, you can check to see if it's IE before running this code using the snippet from check for IE browser