Horizontal scroll on one child element in parent - html

I have a page with several sections (see code snippet or JSFiddle example).
The user should only be able to scroll vertically on the page.
Now, aside from that, I would like to horizontally scroll through only one section: the projects (without affecting the rest of the page). That means that, apart from the projects section, the rest will have to stay still.
How could I achieve this partial horizontal scroll?
.container {
width: 500px;
height: 100%;
overflow-x: scroll;
background-color: lightgrey;
padding: 20px;
}
.projects {
width: 960px;
}
.project {
display: inline-block;
float: left;
width: 300px;
margin: 0 20px 20px 0;
background-color: grey;
}
<div class="container">
<h1>Page</h1>
<div class="main">
<h2>Main</h2>
<p>Lorem ipsum dolor sit amet.</p>
</div>
<div class="projects">
<h2>Projects</h2>
<div class="project">
<p>Project</p>
</div>
<div class="project">
<p>Project</p>
</div>
<div class="project">
<p>Project</p>
</div>
</div>
</div>

Try this.
.projects .project-inwrap {
width: 100%;
white-space: nowrap;
overflow: auto;
}
.container {
width: 500px;
height: 100%;
overflow-x: scroll;
background-color: lightgrey;
padding: 20px;
}
.projects .project-inwrap {
width: 100%;
white-space: nowrap;
overflow: auto;
}
.project {
display: inline-block;
width: 300px;
margin: 0 20px 20px 0;
background-color: grey;
}
<div class="container">
<h1>Page</h1>
<div class="main">
<h2>Main</h2>
<p>Lorem ipsum dolor sit amet.</p>
</div>
<div class="projects">
<h2>Projects</h2>
<div class="project-inwrap">
<div class="project">
<p>Project</p>
</div>
<div class="project">
<p>Project</p>
</div>
<div class="project">
<p>Project</p>
</div>
</div>
</div>
</div>

Try this
*{
box-sizing: border-box;
}
body{
overflow: hidden;
}
.container {
width: 500px;
height: 100vh;
overflow-x: hidden;
background-color: lightgrey;
padding: 20px;
}
.projects {
width: 100%;
white-space: nowrap;
overflow: auto;
}
.project {
display: inline-block;
width: 300px;
margin: 0 20px 20px 0;
background-color: grey;
}
<div class="container">
<h1>Page</h1>
<div class="main">
<h2>Main</h2>
<p>Lorem ipsum dolor sit amet.</p>
</div>
<div class="projects">
<h2>Projects</h2>
<div class="project">
<p>Project</p>
</div>
<div class="project">
<p>Project</p>
</div>
<div class="project">
<p>Project</p>
</div>
</div>
</div>

Related

Set child width to parent inner width (scroll width / overflow scroll)

I have two rows with columns. The bottom bar later contains blocks which matches the ruler numbers. So both rows should have the same length if one of them exceeds the parent width (overflow scroll).
But currently the bottom bar is always 100% of the initial parent width. But I expected the following:
The first row width increases the inner width of the parent. The bottom row should fill that dynamic width. Is there a way to keep this element separated as it is, but have the same width?
No JavaScript.
There are similar questions and solution on the web / stackoverflow. But nothing works in my case. It looks trivial, but I have no idea. I feel like a noob. ^^ The DOM structure should be retained.
Background: I want to implement a ruler with some annotations at the bottom. Blocks with start and stop. I could use a canvas to achieve that. But I would prefer HTML. I would be grateful for any help.
Stackblitz Demo
body {
width: 100%;
height: 100%;
margin: 0;
}
.container {
width: 100%;
overflow-x: auto;
}
.wrapper {
display: flex;
}
.text {
min-width: 30px;
flex: 1;
text-align: center;
}
.text:nth-child(even) {
background-color: #ddd;
}
.bar {
background-color: green;
height: 30px;
flex: 1;
}
<div class="container">
<div class="wrapper">
<div class="text">1</div>
<div class="text">2</div>
<div class="text">3</div>
<div class="text">4</div>
<div class="text">5</div>
<div class="text">6</div>
<div class="text">7</div>
<div class="text">8</div>
<div class="text">9</div>
<div class="text">10</div>
<div class="text">11</div>
<div class="text">12</div>
<div class="text">13</div>
<div class="text">14</div>
<div class="text">15</div>
<div class="text">16</div>
<div class="text">17</div>
<div class="text">18</div>
<div class="text">19</div>
<div class="text">20</div>
<div class="text">21</div>
<div class="text">22</div>
<div class="text">23</div>
<div class="text">24</div>
<div class="text">25</div>
<div class="text">26</div>
<div class="text">27</div>
<div class="text">28</div>
<div class="text">29</div>
<div class="text">30</div>
</div>
<div class="bar"></div>
</div>
I made it working with one more additional wrapper div for bar and elements.
.scroll {
width: 500px;
overflow: auto;
}
.scroll__wrapper {
width: fit-content;
}
.scroll__elements {
display: flex;
background: pink;
width: fit-content;
}
.text {
flex-shrink: 0;
width: 50px;
}
.scroll__bar {
height: 50px;
background: red;
}
<div class="scroll">
<div class="scroll__wrapper">
<div class="scroll__elements">
<div class="text">1</div>
<div class="text">2</div>
<div class="text">3</div>
<div class="text">4</div>
<div class="text">5</div>
<div class="text">6</div>
<div class="text">7</div>
<div class="text">8</div>
<div class="text">9</div>
<div class="text">10</div>
<div class="text">11</div>
<div class="text">12</div>
<div class="text">13</div>
<div class="text">14</div>
<div class="text">15</div>
<div class="text">16</div>
<div class="text">17</div>
<div class="text">18</div>
<div class="text">19</div>
<div class="text">20</div>
<div class="text">21</div>
<div class="text">22</div>
<div class="text">23</div>
<div class="text">24</div>
<div class="text">25</div>
<div class="text">26</div>
<div class="text">27</div>
<div class="text">28</div>
<div class="text">29</div>
<div class="text">30</div>
</div>
<div class="scroll__bar">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vitae ligula laoreet, iaculis dui sed, ultrices risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
</div>
</div>
You need to set fit-content to min-width of your .container. This works with dynamic width.
See Stackblitz.
body {
width: 100%;
height: 100%;
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
.component {
display: block;
width: 100%;
overflow-x: auto;
}
.container {
display: flex;
flex-direction: column;
min-width: fit-content;
}
.ruler {
display: flex;
}
.text {
flex: 1;
min-width: 30px;
text-align: center;
}
.text:nth-child(even) {
background-color: #ddd;
}
.bar {
position: relative;
background-color: green;
flex: 1;
min-height: 30px;
}
.log {
position: absolute;
left: 30%;
width: 30%;
height: 100%;
background-color: yellow;
display: flex;
justify-content: center;
align-items: center;
}
<div class="component">
<div class="container">
<div class="ruler">
<div class="text">1</div>
<div class="text">2</div>
<div class="text">3</div>
<div class="text">4</div>
<div class="text">5</div>
<div class="text">6</div>
<div class="text">7</div>
<div class="text">8</div>
<div class="text">9</div>
<div class="text">10</div>
<div class="text">11</div>
<div class="text">12</div>
<div class="text">13</div>
<div class="text">14</div>
<div class="text">15</div>
<div class="text">16</div>
<div class="text">17</div>
<div class="text">18</div>
<div class="text">19</div>
<div class="text">20</div>
<div class="text">21</div>
<div class="text">22</div>
<div class="text">23</div>
<div class="text">24</div>
<div class="text">25</div>
<div class="text">26</div>
<div class="text">27</div>
<div class="text">28</div>
<div class="text">29</div>
<div class="text">30</div>
</div>
<div class="bar">
<div class="log"><span>Some Log</span></div>
</div>
</div>
</div>

Flex nowrap container not wrapping child. when the width of those are in mentioned in percentage

I have a flex container that wraps some cards. I have implemented a horizontal scroller with flex(using flex-nowrap). The flex wrapper container is subjected to have a 36px left spacing and a 0px right spacing initially. The catch here is after the last card is scrolled I need to have a 36px right spacing.
here is what I did so far
*{
box-sizing: border-box;
}
h2 {
margin: 0;
}
body {
background: cadetblue;
}
.container {
width: 500px;
margin: 0 auto;
background: #000;
padding: 20px 36px;
}
.scroll-wrapper {
overflow: hidden;
margin-right: -36px;
}
.scroll-inner {
display: flex;
flex-flow: row nowrap;
overflow: auto;
margin: 0px -16px;
}
.card {
height: 250px;
width: 75%;
flex: 1 0 75%;
padding: 0px 16px;
}
.inner-wrapper {
background: #fff;
height: 250px;
}
<div class="container">
<div class="scroll-wrapper">
<div class="scroll-inner">
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
</div>
</div>
</div>
I have given a negative right margin for the wrapper to make it look like it's flowing from the right.
Once the last element is scrolled/reached I want it to look something like this
enter image description here
One thing I noticed is my scroll-inner(flex-nowrap) is not wrapping up the entire children. I presumed if we have five children each having width 50px. The scroll-inner should show a scrollable width of 250px, Unfortunately, it's not how flex is behaving. Any help or suggestion is much appreciated.
Updating few images that show what I'm really looking for
During scrolling
After scrolling till the last card
Try
.scroll-wrapper {
overflow: hidden;
margin: auto;
}
.scroll-inner {
display: flex;
flex-flow: row nowrap;
overflow: auto;
margin: auto;
}
I have found a fix and hope this help someone.
*{
box-sizing: border-box;
}
h2 {
margin: 0;
}
body {
background: cadetblue;
}
.container {
width: 500px;
margin: 0 auto;
background: #000;
padding: 20px 36px;
}
.scroll-wrapper {
overflow: hidden;
margin-right: -36px;
}
.scroll-inner {
display: flex;
flex-flow: row nowrap;
overflow: auto;
margin: 0px;
}
.card {
height: 250px;
width: 75%;
flex: 1 0 75%;
padding-right: 40px;
margin-right: -8px;
}
.inner-wrapper {
background: #fff;
height: 250px;
}
<div class="container">
<div class="scroll-wrapper">
<div class="scroll-inner">
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
<div class="card">
<div class="inner-wrapper"><h2>Card</h2></div>
</div>
</div>
</div>
</div>
Please do answer if someone has a better solution!! Thanks

Stacking divs relative and absolute positions

I'm having a lot of trouble trying to make a layout. I'm trying to make a box overlap an image, I'm trying to use absolute/relative positions but I think I'm doing it wrong. here is the layout
here is the code i have so far:
.trabalhos{
position: relative;
margin-top: 100px;
width: 100%;
max-width: 960px;
}
.caixa{
position: absolute;
left: 0%;
top: auto;
right: auto;
bottom: 10%;
overflow: visible;
width: 30%;
height: auto;
padding: 25px;
border-radius: 10px;
background-color: #333;
color: white;
}
#trabalhos-img-right{
float: right;
}
#trabalhos-img-left{
float: left;
}
#esquerda{
text-align: right;
}
#direita{
text-align: left;
right: 0%;
left: auto;
}
<div class="section-trabalhos">
<div class="container">
<h1>blablablablabla</h1>
<div class="trabalhos">
<div><img id="trabalhos-img-right" src="img-01.png"></div>
<div class="caixa" id="esquerda">
<h2>Lorem ipsum</h2>
<p>blablabla</p>
</div>
</div>
<div class="trabalhos trabalhos_2">
<div><img id="trabalhos-img-left" src="img-01.png"></div>
<div class="caixa" id="direita">
<h2>Lorem ipsum</h2>
<p>blablabla</p>
</div>
</div>
I'll have to make 8 of those, what is the best way?
Thanks in advance
I hope that I have solved this problem
<html>
<head>
<style>
.trabalhos{
width:100%;
max-width: 960px;
height: 60%;
margin-top: 100px;
position: relative;
}
.img{
width:80%;
height: 100%; /*Do not change it*/
}
.caixa{
position: absolute;
bottom:10%;
overflow: visible;
width: 30%;
height: auto;
padding: 25px;
border-radius: 10px;
background-color: #333;
color: white;
}
#trabalhos-img-right{
float: right;
}
#trabalhos-img-left{
float: left;
}
#esquerda{
text-align: right;
left: 0px
}
#direita{
text-align: left;
right: 0px;
}
#trabalhos-img{
width: 100%; /*Do not change it*/
height: 100%; /*Do not change it*/
}
</style>
</head>
<body>
<div class="trabalhos">
<div id="trabalhos-img-right" class="img">
<img id="trabalhos-img" src="img-01.png" /></div>
<div class="caixa" id="esquerda">
<h2>Lorem ipsum</h2>
<p>blablabla</p>
</div>
</div>
<div class="trabalhos">
<div id="trabalhos-img-left" class="img">
<img id="trabalhos-img" src="img-01.png" /></div>
<div class="caixa" id="direita">
<h2>Lorem ipsum</h2>
<p>blablabla</p>
</div>
</div>
</body>
This CodePen could be the solution. Just replace the svg element in the html and css code with your image and you're all set.
Also, this website can help you understanding the position property.
HTML
<div class="container">
<svg width="400" height="110">
<rect width="500" height="500" style="fill:rgb(0,0,255);stroke-width:3;"/>
</svg>
<div class="description">
<h1>Lorem Ipsum</h1>
<h2>Lorem ipsum dolor sit amet</h2>
</div>
</div>
<div class="containersecond">
<svg width="400" height="110">
<rect width="500" height="500" style="fill:rgb(0,0,255);stroke-width:3;"/>
</svg>
<div class="description">
<h1>Lorem Ipsum</h1>
<h2>Lorem ipsum dolor sit amet</h2>
</div>
</div>
CSS
svg {
position: relative;
left: 30px;
}
.description {
background-color: red;
width: 300px;
position: absolute;
top: 70px;
}
.containersecond {
position: absolute;
top: 300px;
}

How to make position sticky work with this structure?

I imagine CSS looks out of place in my example but these styles are added by library, particularily styles in #top, #middle, #bottom. I need .header elements to stick to top.
I've tried all kinds of styles but no luck. Feel free to overwrite or add any styles. How to make this work with the HTML structure I have?
#top {
display: flex;
position: relative;
z-index: 0;
overflow: hidden !important;
max-height: 300px;
max-width: 300px;
border: 2px dashed #ec6161;
}
#middle {
padding-right: 19px;
margin-bottom: -34px;
overflow: scroll;
overflow-x: hidden !important;
min-width: 100%! important;
max-height: inherit !important;
box-sizing: content-box !important;
}
#bottom {
padding-bottom: 17px;
margin-right: -19px;
overflow: scroll;
overflow-y: hidden !important;
box-sizing: border-box !important;
min-height: 100% !important;
}
.header {
position: sticky;
top: 0;
z-index: 1;
background: #eee;
padding: 5px 7px;
font-weight: bold;
}
.content {
height: 100px;
padding: 5px 7px;
}
<div id="top">
<div id ="middle">
<div id="bottom">
<div>
<div>
<div class="header">Header</div>
<div class="content">Content</div>
</div>
<div>
<div class="header">Header</div>
<div class="content">Content</div>
</div>
<div>
<div class="header">Header</div>
<div class="content">Content</div>
</div>
<div>
<div class="header">Header</div>
<div class="content">Content</div>
</div>
<div>
<div class="header">Header</div>
<div class="content">Content</div>
</div>
</div>
</div>
</div>
</div>
Also: https://jsfiddle.net/bkn0e3gL/2/
Setting overflow: hidden on any parent divs seems to be causing the problem.
Check out this answer:
if you set overflow to hidden on any ancestor of your sticky element, then this ancestor element will be the scrolling container for your sticky element.
.header {
background: #B8C1C8;
border-bottom: 1px solid #989EA4;
border-top: 1px solid #717D85;
color: #FFF;
position: -webkit-sticky;
position: sticky;
top: -1px;
}
.content {
min-height: 200px;
}
#bottom {
padding-bottom: 17px;
margin-right: -19px; //overflow: scroll;
//overflow-y: hidden !important;
box-sizing: border-box !important;
min-height: 100% !important;
}
#middle {
padding-right: 19px;
margin-bottom: -34px; //overflow: scroll;
//overflow-x: hidden !important;
min-width: 100% ! important;
max-height: inherit !important;
box-sizing: content-box !important;
}
#top {
display: flex;
position: relative;
z-index: 0;
//overflow: hidden !important;
max-height: 300px;
max-width: 300px;
border: 2px dashed #ec6161;
}
<div id="top">
<div id="middle">
<div id="bottom">
<div>
<div>
<div class="header">Header</div>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque viverra.</div>
</div>
<div>
<div class="header">Header</div>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque viverra.</div>
</div>
<div>
<div class="header">Header</div>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque viverra.</div>
</div>
<div>
<div class="header">Header</div>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque viverra.</div>
</div>
</div>
</div>
</div>
</div>

CSS for Individual Columns Scroll with Horizontal Scrolling

I am building a UI component that has columns of information. Each column needs to be individually scrollable. I have found that on SO.com before, but I am having trouble reconciling that with the other requirement - that the page scrolls horizontally to show columns that do not fit on screen.
I have the horizontal scrolling working but cannot get it to work in conjunction with individual column scrolling. The code:
#board {
float: left;
height: 98%;
max-height: 98%;
width: 4300px; /*smaller than columns to force horizontal scroll */
margin: auto;
border: none;
overflow-x: scroll;
}
#columns {
height: 98%;
float: left;
width: 4800px; /* need this much width */
margin: auto;
border: none;
overflow-x:auto;
}
.column {
float: left;
padding-bottom: 50px;
width: 240px;
height: 100%;
max-height: 100%;
padding: 5px;
padding-bottom: 100px;
margin-left: 5px;
overflow-y: auto;
overflow-x: hidden;
}
<div id="board">
<div id="columns">
<div id="col1" class="column">
<div class="card"> ...content... </div>
<div class="card"> ...content... </div>
<div class="card"> ...content... </div>
<div class="card"> ...content... </div>
</div>
<div id="col2" class="column">
<div class="card"> ...content... </div>
<div class="card"> ...content... </div>
<div class="card"> ...content... </div>
<div class="card"> ...content... </div>
</div>
<!-- 12-16 more columns -->
</div>
</div>
Edited to fix id vs class issue in html.
I tried to simplify your code to only include what's necessary to solve your problem, but it should work. There are a couple errors in your CSS too: you have a style for #boards but the outer container has a class boards not an id, and you have a style for #columns but the middle inner container has an id of positions.
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
.board {
height: 100%;
width: 200px;
overflow-x: scroll;
}
#columns {
height: 100%;
width: 500px;
white-space: nowrap;
}
.column {
vertical-align: top;
height: 100%;
display: inline-block;
width: 150px;
overflow-y: auto;
overflow-x: hidden;
}
.card {
height: 200px;
background: #F00;
margin-bottom: 5px;
}
<div class="board">
<div id="columns">
<div class="column">
<div class="card">...content...</div>
<div class="card">...content...</div>
<div class="card">...content...</div>
<div class="card">...content...</div>
</div>
<div class="column">
<div class="card">...content...</div>
<div class="card">...content...</div>
<div class="card">...content...</div>
</div>
<div class="column">
<div class="card">...content...</div>
</div>