Prevent scrolling on element with "overflow: hidden"? - javascript

overflow: hidden prevents users from scrolling with input devices, but it's still possible to scroll the element with focus(), scrollIntoView(), etc. I have some content that should be hidden with overflow: hidden, but calling focus() on a hidden input sometimes causes the browser to scroll the overflow: hidden element and reveal the hidden content.
Here's a demo where the right element should always be hidden:
document.querySelector('input').focus();
// document.querySelector('.right').scrollIntoView(); works too
body {
overflow: hidden;
margin: 0;
}
.container {
width: 200vw;
display: flex;
}
.left {
width: 100vw;
border: 1px solid red;
}
.right {
width: 100vw;
border: 1px solid blue;
}
<div class="container">
<div class="left">left</div>
<div class="right">
right
<input />
</div>
</div>
Adding position: fixed to .right fixes this issue, but it introduces other styling issues. Is it possible to make body never scrollable without using position: fixed?
The issue I'm facing is caused by React calling focus() when a hidden input has the autoFocus property. It's called in ReactDOMHostConfig's commitMount. Even if I add a lint rule to disable React's autoFocus, it's likely that someone will call focus() and cause a bug.

You set overflow: hidden on both the html and body elements so that the body will not be scrollable. Then, you set overflow: scroll on the .right element, so that if focus() is called on a hidden input, the .right element will scroll instead of the body.
html,
body {
height: 100%;
overflow: hidden;
}
.container {
width: 200vw;
height: 100%;
display: flex;
}
.left {
width: 100vw;
height: 100%;
border: 1px solid red;
}
.right {
width: 100vw;
height: 100%;
border: 1px solid blue;
overflow: scroll;
}

With javascript
document.querySelector('input').focus();
document.querySelector('.right').scrollIntoView();
document.querySelector('.left').addEventListener('click', function(event) {
document.querySelector('input').focus();
document.querySelector('.right').scrollIntoView();
console.log('focus input');
});
// Reset the scroll from javascript
window.onscroll = function() {
window.scrollTo(0, 0);
console.log('reset scroll');
};
body {
overflow: hidden;
margin: 0;
}
.container {
width: 200vw;
display: flex;
}
.left {
width: 100vw;
border: 1px solid red;
}
.right {
width: 100vw;
border: 1px solid blue;
}
<div class="container">
<div class="left">left - click me</div>
<div class="right">
right
<input />
</div>
</div>

Related

how to hide scrollbar in html?

I want to hide scrollbar, but at the same, i also want to have scrolling action i.e
I want to hide scrollbar but still, want to scroll to see rest of content without actually seeing the scrollbar.
overflow: hidden won't work because after using that I cannot scroll to see the content.
how to do that using HTML/CSS/javascript?
I am working on styling scrollbar but I noticed there is no well-defined way to style scroll bar so I made custom scrollbar using divs with jQuery, but at the end, I have two scroll bar one which I made and other default scrollbar and now I want to hide default scroll bar.
I don't want to use -webkit- because it is not accepted in all browser.
I want to hide scroll bar in the following code.
.container{
width: 100%;
background-color: #d5d5d5;
}
.sidebarcontainer{
width: 300PX;
height: 6000px;
display: inline-block;
box-sizing: border-box;
padding: 5px;
padding-right: 2px;
}
.innersidebarcontainer{
position: relative;
width: 100%;
height: 100%;
}
.sidebar{
width: 300px;
background-color: teal;
height: 2000px;
top: 1px;
position: absolute;
}
.mainpage{
width: calc(100% - 300px);
padding: 5px;
padding-right: 2px;
height: 6000px;
display: inline-block;
box-sizing: border-box;
}
.page{
width: 100%;
height: 100%;
background-color: white;
}
.footer{
height: 500px;
width: 100%;
margin: 0 auto;
background-color: purple
}
<body>
<div class="container">
<div class="sidebarcontainer">
<div class="innersidebarcontainer">
<div class="sidebar">
</div>
</div>
</div>
<div class="mainpage">
<div class="page"></div>
</div>
</div>
<div class="footer"></div>
</body>
please anybody answer!
And overflow:auto; is out of the question?
It won't show if you don't need but does show when you do.
You need to add the following styles:
#parent {
height: 100%;
width: 100%;
overflow: hidden;
}
#child {
width: 100%;
height: 100%;
overflow-y: scroll;
padding-right: 17px;
}
Here is the working fiddle: http://jsfiddle.net/5GCsJ/954/
Make your scroll bar transparent. You can do this by the following code.
::-webkit-scrollbar
{
width:0px;
}
::-webkit-scrollbar-track-piece
{
background-color: transparent;
}
Hope this will help you!
Try this:
yourDiv::-webkit-scrollbar{
width: 0px;
}

Vertically center a child <div> within a parent <div> when parent has display: block;

I am trying to vertically center a child div that has contenteditable so users may type in the middle of the parent div, so the text needs to be vertically centered.
The parent div must have it's display set to block because I need it's top and bottom borders to have the max height of it's container, as it will be selected for a resizing event.
I have tried many methods such as flexbox and vertical align but they all require me to change the parent's display property which I can't see any way around. I'll even accept a JS solution if it works and isn't too cumbersome.
div {
border: 1px solid black;
max-width: 100px;
outline: none;
}
.parent {
display: block;
padding: 0;
margin: 0;
width: 100%;
height: 300px;
}
.child {
display: table-cell;
height: 100%;
width: 100%;
max-width: 80px;
padding: 10px;
overflow: hidden;
vertical-align: middle;
text-align: center;
white-space: pre-wrap;
word-wrap: break-word;
}
<div class="parent" align="center">
<div contenteditable=true class="child">
</div>
</div>
One way to do it would be to use these CSS rules:
.parent {
display: block;
width: 100%;
height: 300px;
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
See complete solution:
http://codepen.io/shippin/pen/yMKMpR
Also note you have some issues in your html:
missing quotes on contenteditable="true"
The align attribute is not supported in HTML5.

On display of hidden element it shows on wrong place because of scroll, only in chrome

I don't realy know how to explain this thing in short sentence.
I don't know if it is bug or not..
In parent div with fixed height and overflow-y scroll, I have multiple children elements, which has jquery function click, what displays hidden element in these divs. When I scroll down to last div, after click, hidden element displays in wrong place.
I tried to search for this problem, cause it should be pretty common. But nothing came up.s
It's realy hard to explain with words. Just look at this jquery example with mozilla and after that with chrome.
https://jsfiddle.net/zvwcdzjz/2/#
P.S. I need my original example work and look exactly the same on chrome and mozilla, cause right now on mozilla everything looks exactly as i want it to be, but it bugs on chrome.
It can be solved with jQuery too, makes no difference for me.
HTML:
<div id="el">
<div class="content">
<div class="block">
<div class="blocktoopen"></div>
<div class="button">click to open</div>
</div>
<div class="block">
<div class="blocktoopen"></div>
<div class="button">click to open</div>
</div>
<div class="block">
<div class="blocktoopen"></div>
<div class="button">click to open</div>
</div>
</div>
</div>
CSS:
#el {
width: 300px;
height: 400px;
overflow-x: hidden;
overflow-y: scroll;
background-color: rgba(0,0,0,0.1);
}
#el .content {
width: 300px;
height: auto;
}
.block {
width: 300px;
height: 200px;
margin-top: 10px;
background-color: rgba(0,0,0,0.2);
}
.button {
background-color: blue;
color: #fff;
cursor: pointer;
text-align: center;
margin-top: 90px;
float: left;
}
.blocktoopen {
width: 50px;
height: 50px;
position: absolute;
margin-left: 300px;
background-color: red;
display: none;
}
JS:
$(function(){
$(".button").click(function(){
$(this).parent(".block").children(".blocktoopen").show();
});
$("#el").scroll(function(){
$(".blocktoopen").hide(); });
});
The set height of #el was causing the red box to appear in the incorrect location. I have removed this. See the example below:
Change:
#el {
width: 300px;
height: 400px;
overflow-x: hidden;
overflow-y: scroll;
background-color: rgba(0,0,0,0.1);
}
To:
#el {
width: 300px;
overflow-x: hidden;
overflow-y: scroll;
background-color: rgba(0,0,0,0.1);
}
And then you're good to go.
To make your life simpler make the parent .bloc relative so the blocktoopen will be computed relatively. Will help with the responsiveness.
.block {
width: 300px;
height: 200px;
margin-top: 10px;
background-color: rgba(0,0,0,0.2);
position: relative;
}
.blocktoopen {
width: 50px;
height: 50px;
position: absolute;
top: 50%;
bottom: 50%;
background-color: red;
display: none;
right: 0;
}
I can't post comment so here is another try with jsfiddle. I am not sure if you have horizontal scroll as well. remove margin-right from .blocktoopen and add right:0; Also wrap all your internal content inside a div and set the width to maybe 225px
#el {
width: 300px;
height: 400px;
overflow-x: hidden;
overflow-y: scroll;
background-color: rgba(0,0,0,0.1);
}
#el .content {
width: 300px;
height: auto;
}
.block {
width: 300px;
height: 200px;
margin-top: 10px;
background-color: rgba(0,0,0,0.2);
position: relative;
}
.button {
background-color: blue;
color: #fff;
cursor: pointer;
text-align: center;
margin-top: 90px;
float: left;
}
.blocktoopen {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
display: none;
top: 50%;
bottom: 50%;
right: 0;
}
.internal{
width: 225px;
}
Have you tried to click on 2 buttons without scrolling? Try it. Looks like you were using visibility: hidden; and not display: none;. Maybe trying to set the position: relative; ...
Just seen the jquery script. Show() and hide() appears to work as visibility css property.
If u look with Chrome DevTools the jsFiddle example you will see that you can't see the red boxes but they are still there.

How browser renders HTML

I am trying to create a structure similar to panels. This is what i have tried:
FIDDLE
<div id='main'>
<div id='firstp'>Panel 1</div>
<div id='secondp'>Panel 2
<div id='slide'>Panel 3</div>
</div>
</div>
and CSS is
#main{
width: 300px;
height: 300px;
border: 1px solid black;
}
#firstp{
width: 20%;
height: 100%;
border: 1px solid blue;
display: inline-block;
}
#secondp{
width: 20%;
height: 100%;
border: 1px solid red;
display: inline-block;
position: relative;
background-color: red;
}
#slide{
width: 100%;
height: 100%;
position: absolute;
border: 1px solid green;
background-color: green;
}
I am curious to know how browser renders HTML while parsing. As we can see there are three panels, Panel 3 being child of Panel 2, is seen on top of Panel 2. Whereas as per requirement , Panel 2 should be on top of Panel 3 and say when i click on some button in panel 2, panel 3 should slide behind panel 2 and comes forward on right side of panel 2. Hope i made myself clear. Please help.
If you want panel 2 to be on top of panel 3 then you will need to apply something like z-index:-1;.
I have modified your fiddle to show this working.
Panel 3 is behind panel 2 as you requested and there is a button that when clicked transforms the panel to the right. You can easily neaten this up to hide the entire panel and do some cool jQuery stuff to make the slide transition nicer.
Just try to remember that unless you say otherwise, children will usually appear in front of their parent.
This isn't about browser rendering, it's your CSS that's making the children exceed the height of the parent.
Because you've fixed the height of the parent, yet you've said that #slide is 100% in height, but there's another child of #secondp, which is the text node Panel 2. So technically, #secondp has a height of 100% + height of Panel 2, hence the overflow.
To remedy this, put the text node Panel 2 inside an element, then set the height of that element (I've used 10%) and then adjust the height of #slide to be 100% - specified height of the new element.
Here's an example:
Fiddle
HTML:
<div id='main'>
<div id='firstp'>Panel 1</div>
<div id='secondp'>
<div id="slide1">Panel 2</div>
<div id='slide'>Panel 3</div>
</div>
</div>
CSS:
#main{
width: 300px;
height: 300px;
border: 1px solid black;
}
#firstp{
width: 20%;
height: 100%;
border: 1px solid blue;
display: inline-block;
vertical-align: top;
box-sizing: border-box;
}
#secondp{
width: 20%;
height: 100%;
border: 1px solid red;
display: inline-block;
position: relative;
background-color: red;
box-sizing: border-box;
}
#slide{
width: 100%;
height: 90%;
position: relative;
border: 1px solid green;
background-color: green;
box-sizing: border-box;
}
#slide1 {
height: 10%;
}
You'll also notice I've added vertical-align: top to firstp aswell, otherwise it'll be off the top.
Also, I've added box-sizing: border-box to prevent the border overlapping the parent.
#main{
width: 300px;
height: 300px;
border: 1px solid black;
}
#main>div{
width: 20%;
height: 100%;
border: 1px solid blue;
display: inline-block;
}
#main>div{
width: 20%;
height: 100%;
border: 1px solid red;
display: inline-block;
position: relative;
background-color: red;
}
#slide{
width: 100%;
height: 100%;
position: absolute;
border: 1px solid green;
background-color: green;
}

Loading an Image in `<div>` overrides html text

I'm writing an html page that should have the following behavior:
When loaded it contains an empty <div> with a link inside it.
Once pressed the link runs the script StartTrial.js which is supposed to load an image from a directory, visualize it, and give some instructions on what to do.
However, as you can see, once the image is loaded it covers the instructions. This is cause the instructions are written in a <div> that has a margin of 30px from the container <div> with its size before loading the image. How can I fix my code so that the text is always shown with a 30px margin from the bottom of the image?
Here are my code snippets:
Html
<div id="container">
Start Trial
<img class="displays" id="t1_img" src="./images/immi.jpg">
</div>
<div class="instruction" id="instr_1">
<p><b>Instruction:</b><p>
<p>Some text here.</p>
</div>
CSS
#container {
position: relative;
background: gray;
width: 300px;
height: 300px;
margin: 30px;
}
.displays {
position: absolute;
display: none;
top: 0px;
left: 0px;
}
JavaScript
function StartTrial() {
$('#startTrial').hide();
$('#t1_img').show();
$('#instr_1').show();
}
Change your css to use min-height and min-width
#container {
position: relative;
background: gray;
min-width: 300px;
min-height: 300px;
margin: 30px;
}
and remove the absolute positioning, as there is no real need for it.
.displays {
display: none;
top: 0px;
left: 0px;
}
Your image is larger than the container and hence it is overlapping the instructions.
No need to over-engineer it, you can have a css only solution or a simple JS one as follows:
CSS only solution
HTML:
<input type="checkbox" id="startCheckbox" class="start-checkbox"/>
<div id="container" class="container">
<label for="startCheckbox" class="start-trial center">Start Trial</label>
<div class="instruction center" id="instr_1">
<p><b>Instruction:</b></p>
<p>Some text here.</p>
</div>
</div>
CSS:
.center {
position: absolute;
top:0; right:0; bottom:0; left:0;
margin: auto;
}
.container {
border: 1px solid #ccc;
width: 400px;
height: 400px;
position: relative;
}
.container .instruction {
border: 1px dashed #333;
background: rgba(255,238,221,.9);
width: 250px;
height: 250px;
padding: 25px;
text-align: center;
display: none;
}
.container .start-trial {
position: absolute;
height: 20px;
width: 80px;
text-decoration: underline;
cursor: pointer;
}
.container .start-checkbox {
display: none;
}
.start-checkbox {
display: none;
}
.start-checkbox:checked ~ .container .start-trial {
display: none;
}
.start-checkbox:checked ~ .container .instruction {
display: block;
}
.start-checkbox:checked ~ .container {
background: url(http://www.ceritaspros.com/dev/images/dogs/FunnyPuppies/funny-puppies-sleeping-400x400.jpg);
}
Fiddle: http://jsfiddle.net/qobbkh6f/5/
CSS+JS Solution
HTML:
<div id="container" class="container">
Start Trial
<div class="instruction center" id="instr_1">
<p><b>Instruction:</b></p>
<p>Some text here.</p>
</div>
</div>
CSS:
.center {
position: absolute;
top:0; right:0; bottom:0; left:0;
margin: auto;
}
.container {
border: 1px solid #ccc;
width: 400px;
height: 400px;
position: relative;
}
.container .instruction {
border: 1px dashed #333;
background: rgba(255,238,221,.9);
width: 250px;
height: 250px;
padding: 25px;
text-align: center;
display: none;
}
.container.clicked {
background: url(http://www.ceritaspros.com/dev/images/dogs/FunnyPuppies/funny-puppies-sleeping-400x400.jpg);
}
.container.clicked .start-trial {
display: none;
}
.container.clicked .instruction {
display: block;
}
.copntainer.clicked .instruction {
display: block;
}
.container .start-trial {
position: absolute;
height: 20px;
width: 80px;
}
JS:
$("#container").on("click", "#startTrial", function(e) {
e.preventDefault();
$("#container").addClass("clicked");
});
Fiddle: http://jsfiddle.net/qobbkh6f/3/
Try this and let me know if it helps
HTML
<div id="container">
Start Trial
<img class="displays" id="t1_img" src="./images/immi.jpg">
</div>
<div class="instruction" id="instr_1">
<p><b>Instruction:</b><p>
<p>Some text here.</p>
</div>
CSS
#container {
position: relative;
background: grey;
width: 300px;
height: 300px;
margin: 30px;
overflow:hidden
}
.displays {
position: absolute;
top: 0px;
left: 0px;
max-height:100%;
}
Javascript
function StartTrial() {
$('#startTrial').hide();
$('#t1_img').show();
$('#instr_1').show();
}
http://jsfiddle.net/5jx3dn44/
Don't use absolute positioning on your image.
The whole concept of absolute positioning is to make an element overlap the other elements on the page. If you don't want something to overlap other elements then don't use it.
Also don't give a size to your container. It's not the container that's 300x300 and grey - it's your start trial block. If the container is invisible and flexible then it will look good with the image in it when you remove the start trial block. I forget how hide() works but just change to display:none if it doesn't actually remove the element from the layout.

Categories