Scrollable CSS div with fixed parent element - javascript

I am building a mobile application which will have a scrollable element in the middle of the screen. Currently when I try and scroll the entire app moves. I would like the all other elements to remain fixed while my element scrolls.
Here is my main React App:
class MobileServices extends Component {
render() {
return (
<div className={style.app}>
<div className={style.mobileHeader}>
<div className={style.logoBox}>
Logo Here
</div>
<div className={style.contactBox}>
</div>
</div>
<div className={style.mainContent}>
<div className={style.contentOne}></div>
<div className={style.contentTwo}></div>
<div className={style.contentThree}></div>
</div>
</div>
);
}
}
Here is the CSS:
html, body {
margin: 0;
/* height: 100% */
}
.app {
background-color: green;
background-size : cover;
background-attachment: fixed;
height: 100vh;
width: 100vw;
overflow: hidden;
}
.contactBox {
margin: 1rem;
padding: 1rem;
}
.contentOne {
background-color: blue;
display: flex;
height: 10rem;
width: 100vw
}
.contentTwo {
background-color: red;
display: flex;
height: 10rem;
width: 100vw
}
.logoBox {
border: 2px solid white;
margin: 1rem;
padding: 2rem;
}
.mainContent {
flex: 1;
display: flex;
overflow: scroll;
margin-top: 4rem;
height: 10rem;
width: 300vw;
overflow-x: auto;
}
.mobileHeader {
display: flex;
justify-content: space-between;
width: 100%;
}
I have tried making the app class fixed, but that only prevented me from being able to scroll at all.

body, html {
width: 100%;
height: 100%;
overflow: hidden;
}
.app {
// your css and
display: flex;
flex-direction: column;
}
.mainContent {
flex-grow: 1;
overflow: auto;
// rest of your css
}
Optional, you can set your mobielHeader to have position: sticky

Related

How to make a modal background fill the entire page, even when there is a scroll?

I have a modal for editing some content, and while I want the background for the modal to fill the entire visible screen, the form (the modal content) has a fixed height.
Issues arise when the viewport has a smaller height. There is a scroll after opening the modal, and when you scroll, part of the background doesn't show at the bottom.
How can I make it stretch to fill the entire height of the body element? Here is a JSFiddle and my code below:
document.addEventListener('click', function() {
const modal = document.querySelector('.modal');
modal.classList.toggle('hidden');
});
* {
margin: 0;
padding: 0;
}
body {
height: 100%;
}
.flex {
width: 100%;
height: 100vh;
background-color: #999999;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.modal {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
}
.modal.hidden {
display: none;
}
.modal_content {
margin: auto 0;
width: 100px;
height: 300px;
background-color: #999999;
border: 3px solid red;
}
<body>
<div class="flex">
<p>Click anywhere in the document to add/remove the modal</p>
<p>Resize the window so the modal is too tall, then try to scroll</p>
</div>
<div class="modal hidden">
<div class="modal_content">
</div>
</div>
</body>
You could resolve this issue by setting on the modal a position fixed instead of an absolute one as you did. Like so:
document.addEventListener('click', function() {
const modal = document.querySelector('.modal');
modal.classList.toggle('hidden');
});
* {
margin: 0;
padding: 0;
}
body {
height: 100%;
}
.flex {
width: 100%;
height: 100vh;
background-color: #999999;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.modal {
position: fixed; /* line I changed */
overflow:auto; /* line I added */
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
}
.modal.hidden {
display: none;
}
.modal_content {
margin: auto 0;
width: 100px;
height: 300px;
background-color: #999999;
border: 3px solid red;
}
<div class="flex">
<p>Click anywhere in the document to add/remove the modal</p>
<p>Resize the window so the modal is too tall, then try to scroll</p>
</div>
<div class="modal hidden">
<div class="modal_content">
</div>
</div>
Everything is on its place but you need to use position:fixed not absolute
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
}
when using absolute then you'll be placing your modal absolutely inside relative or fixed or another absolute positioned parent or grandparent of that modal,
but using fixed you're placing your modal relative to browser window not its div or other sorts of parent

Modal height resizes to content, but at max-height of modal content becomes scrollable

I have a modal that contains tabs that potentially will have long content.
What I'm trying to do is get the modal to resize on content height but when the content exceeds the modals max-height of 80% the content section should become scrollable.
currently, it works that content scrolls when it gets too large. but the problem is now the modal__content container stays 100% height regardless of the content. if I remove the height from modal__content then the content scroll no longer works.
Hope this makes sense
<div class="modal">
<div class="modal__container">
<div class="modal__content">
<div class="modal__left"></div>
<div class="modal__right>lorem 200 </div>
</div>
</div>
<div>
<div class="modal-overlay"></div>
CSS
html, body {
height: 100%;
}
*, ::after, ::before {
box-sizing: border-box;
}
.modal {
width: 100%;
height: 100%;
background: rgba(0,0,0,.7);
position: fixed;
left: 0;
top: 0;
}
.modal__container {
width: 1076px;
display: flex;
align-items: center;
height: calc(100% - 3.5rem);
margin:1.75rem auto;
}
.modal__content {
background: white;
display: flex;
height: 100%;
}
.modal__left {
width: 400px;
background: #f6f6f6;
}
.modal__right {
flex: 1;
display: flex;
align-items: center;
}
.modal__inner {
padding: 2.5rem;
}
.modal__body {
padding: 0 2.5rem;
height: calc(100% - 5rem);
overflow-y: scroll;
}
Try adding
overflow-y: scroll;
to .modal__content
You could also try switching the heights from
height: calc(100% - 3.5rem);
to
height: 100vh;

ScrollIntoView breaks the overflow scroll

I have a nested child container and when I'm trying to scrollIntoView it breaks the parent container. I'm not able to understand why it's acting like this. Please help me out in this.
Please have a look at the code below or on jsfiddle
function moveToTop() {
console.log('MOVE TO TOP::');
const child = document.getElementById('child');
child.scrollIntoView({
behavior: "smooth"
});
}
#parent {
background-color: blue;
padding: 10px;
height: 500px;
overflow: hidden;
display: flex;
flex-direction: column;
}
#scroller {
overflow: auto;
padding: 10px;
background-color: red;
flex-grow: 1;
}
#child {
height: 10000px;
background-color: green;
}
body {
overflow: hidden;
color: #fff;
font-weight: bold;
}
button {
position: fixed;
bottom: 20px;
width: 140px;
left: 20%;
right: 0;
}
<div id="parent">
PARENT
<div id="something">Something</div>
<div id="scroller">
CHILD
<div id="child">
GRAND CHILD
<button onclick="moveToTop()">Top</button>
</div>
</div>
</div>
The whole problem is that scrollIntoView() is moving the window. But since the #parent overflow is hidden, when the window is moved, this element itself breaks. I could suggest setting a position: fixed for the #parent, which will solve your problem, but it can harm the layout in general.
Use the scroll() method. The scrolling mechanism itself is:
scroller.scroll(0, child.offsetTop - 55);
child.offsetTop - top element;
55 - distance from the top of the #parent to the top #scroller.
The transition animation must be set to css, in selector #scroller. Like that:
#scroller {
...
scroll-behavior: smooth;
}
function moveToTop() {
console.log('MOVE TO TOP::');
const child = document.getElementById('child');
const scroller = document.getElementById('scroller');
scroller.scroll(0, child.offsetTop - 55);
}
#parent {
background-color: blue;
padding: 10px;
height: 500px;
overflow: hidden;
display: flex;
flex-direction: column;
}
#scroller {
overflow: auto;
padding: 10px;
background-color: red;
flex-grow: 1;
scroll-behavior: smooth;
}
#child {
height: 10000px;
background-color: green;
}
body {
overflow: hidden;
color: #fff;
font-weight: bold;
}
button {
position: fixed;
bottom: 20px;
width: 140px;
left: 20%;
right: 0;
}
<div id="parent">
PARENT
<div id="something">Something</div>
<div id="scroller">
CHILD
<div id="child">
GRAND CHILD
<button onclick="moveToTop()">Top</button>
</div>
</div>
</div>

Why scroll hides some elements when it's container have full width?

I have a div that is 100vw of width and is scrollable with dynamic elements. However, once you add more items, the first will suddenly disappearing once is not visible even if you try to scroll out.
This is more testable on mobile phones, once the view width is smaller.
My question is: How I can achieve a natural scroll with all items being visible with a view width of 100vw?
html, body {
height: 100vh;
width: 100vw;
}
#images {
overflow-x: scroll;
display: flex;
align-items: center;
justify-content: center;
height: 35vh;
width: 100vw;
img {
height: 20vh;
width: 20vh;
margin-right: 1.5rem;
cursor: pointer;
}
}
const App: React.FC = () => {
const [photos, setPhotos] = React.useState<string[]>([])
React.useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/photos')
.then(res => res.json())
.then(data => data && setPhotos(data.filter(p => p.id < 11).map(p => p.url)))
}, [])
return (
<div id='images'>
{photos.length && photos.map((p, i) => (
<img key={`${i}${p}`} src={p} alt='mock'/>
))}
</div>
)
}
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.querySelector('#root')
);
Code pen: https://codepen.io/mdsp9070/full/bGeGXyg
This what you mean? Flex wrap or grid will give you this effect.
html, body {
height: 100vh;
width: 100vw;
}
#images {
overflow-x: scroll;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
width: 100vw;
img {
height: 20vh;
width: 20vh;
margin-right: 1.5rem;
cursor: pointer;
margin-bottom: 12px;
}
}
EDIT*
html, body {
height: 100vh;
width: 100%;
box-sizing: border-box;
}
#images {
margin: 0 auto;
padding: 0 5px;
box-sizing: border-box;
overflow-x: scroll;
display: flex;
align-items: center;
height: 35vh;
width: 100%;
img {
box-sizing: border-box;
height: 20vh;
width: 20vh;
margin-right: 1.5rem;
cursor: pointer;
}
}

How to set div scrollable when content more than size of the page?

I have the next page:
<div id = "menu">
Menu on the left side
</div>
<div id = "header">
Header content of the page
</div>
<div id = "body">
Data Data Data Data Data Data Data
</div>
<div id = "footer">
Additional Information
</div>
Whith Next layout: Menu should be on the left side:
#menu{
background: #244a7c;
padding: 7px 23px 0 7px;
width: 299px;
height: 1000px;
overflow: inherit;
margin-left: 0px;
display: block;
float: left;
}
#header{
display: inline-block;
width: 400px;
border-bottom: 1px solid rgb(238, 238, 238);
}
Body can have different data inside. My problem is:
When content of the body more than user page I want to fix all div except body. Menu should be on the left side, Header should be on the top of the page and footer on the bottom and ONLY body should be scrollable.
Any help, please.
Thanks!
Here's 2 Pure CSS solution
Without fixing any height (header/footer) or width (left column).
I actually prefer the second solution. (even tho he has less browser support)
1 - using CSS tricks
this is a totally responsive design and work well with all browsers (IE10, FF, Chrome, Safari, Opera, mobile browsers)
Working Fiddle
HTML:
<div class="Container">
<div class="Header">
</div>
<div class="HeightTaker">
<div class="Wrapper Container Inverse">
<div>
<div class="Footer">
</div>
</div>
<div class="HeightTaker">
<div class="Wrapper">
<div class="LeftMenu">
</div>
<div class="Content">
</div>
</div>
</div>
</div>
</div>
</div>
CSS:
*
{
margin: 0;
padding: 0;
}
html, body, .Container
{
height: 100%;
}
.Container:before
{
content: '';
height: 100%;
float: left;
}
.HeightTaker
{
position: relative;
z-index: 1;
}
.HeightTaker:after
{
content: '';
clear: both;
display: block;
}
.Wrapper
{
position: absolute;
width: 100%;
height: 100%;
}
.Inverse, .Inverse > *
{
-moz-transform: rotateX(180deg);
-ms-transform: rotateX(180deg);
-o-transform: rotate(180deg);
-webkit-transform: rotateX(180deg);
transform: rotateX(180deg);
}
.LeftMenu
{
height: 100%;
float: left;
}
.Content
{
overflow: auto;
height: 100%;
}
/*For demonstration only*/
p
{
font-size: 1.3em;
}
.Important
{
font-weight: bolder;
color: white;
}
body > .Container
{
text-align: center;
}
.Header
{
background-color: #bf5b5b;
}
.LeftMenu
{
background-color: #bdbe4c;
}
.Content
{
background-color: #90adc1;
}
.Footer
{
background-color: #b5a8b7;
}
2 - using Flex
This layout can also be achieved using flex, but the current browser support is pure.
Here's a Working Fiddle only FF,Chrome,IE10.
HTML: (simpler)
<header>
</header>
<section class="Middle">
<div class="LeftMenu">
</div>
<div class="Content">
</div>
</section>
<footer>
</footer>
CSS:
*
{
margin: 0;
padding: 0;
}
html, body
{
height: 100%;
text-align: center;
}
body
{
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.Middle
{
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 0;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
overflow: hidden;
}
.Content
{
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 0 0;
overflow: auto;
}
/*For demonstration only*/
p
{
font-size: 1.3em;
}
.Important
{
font-weight: bolder;
color: white;
}
header
{
background-color: #bf5b5b;
}
.LeftMenu
{
background-color: #bdbe4c;
}
.Content
{
background-color: #90adc1;
}
footer
{
background-color: #b5a8b7;
}
If you set the header, footer & menu position as fixed & leave the body as it is, it should work. Only the body will be scrollable.
#header {
position: fixed;
top: 0;
display: inline-block;
width: 400px;
border-bottom: 1px solid rgb(238, 238, 238);
}
#footer {
position: fixed;
bottom: 0;
}
#menu {
position: fixed;
left: 0;
background: #244a7c;
padding: 7px 23px 0 7px;
width: 299px;
height: 1000px;
}
#body {
margin-left: 300px;
margin-top: <header-height>;
margin-bottom: <footer-height>;
}

Categories

Resources