I have a container, and contents that I want to be horizontally scrollable. It's dynamically generated, so I can't know exactly how wide the contents will be.
So the problem is that the styling (background, border, etc) that I apply to the content only effects the area initially visible. When you scroll rightward, any additional content that comes into view is missing styling. This is because the elements they're applied to have 100% the width of the container, but the contents they contain extend past their limits.
This is an example of what I mean: fiddle
.wrapper {
position: relative;
width: 100px;
height: 100px;
border: 1px black solid;
overflow-x: scroll;
}
.slider {
position: relative;
height: 100%;
background: white;
}
.line {
height: 20px;
white-space: nowrap;
border-bottom: 1px solid black;
}
.line-item {
position: relative;
display: inline-block;
width: 30px;
}
<div class="wrapper">
<div class="slider">
<div class="line">
<div class="line-item">item</div>
<div class="line-item">item</div>
<div class="line-item">item</div>
<div class="line-item">item</div>
<div class="line-item">item</div>
</div>
</div>
</div>
In this example, the contents of .line extend past .line, so of course the border and background aren't applied. How can I get the border and background to extend to the entire contents of .line?
In other words, how can I get .line to take more than 100% width?
Make the slider display as an inline block
.wrapper {
position:relative;
width:100px;
height:100px;
border: 1px black solid;
overflow-x:scroll;
}
.slider {
display: inline-block; /* added */
position:relative;
height:100%;
background:white;
}
.line {
height:20px;
white-space:nowrap;
border-bottom:1px solid black;
}
.line-item {
position:relative;
display:inline-block;
width:30px;
}
<div class="wrapper">
<div class="slider">
<div class="line">
<div class="line-item">item</div>
<div class="line-item">item</div>
<div class="line-item">item</div>
<div class="line-item">item</div>
<div class="line-item">item</div>
</div>
</div>
</div>
Related
In the snippet below, I want the "title" div to size itself based on its content, so I don't have to specify a width. That bit is obviously working already. I then want the "rightside" div to take the remaining space and right align itself - at the moment it just sits next to the title div.
And of course I don't want to use floats because that messes up everything and we have a no floats policy here.
Based on reading other threads I thought adding an overflow:hidden to one of the parents would make it do this but I can't get it working.
I don't want to specify a width for either div but it will always be the case that one of the parents will have a width specified, so in this case I've set it on the "outer" element.
So how do we get "rightside" to appear to the right of the red box ? thanks
.outer {
width:500px;
border:1px solid red;
}
.outer div {
display:inline-block;
border:1px solid green;
}
.rightside {
width:auto;
text-align: right;
}
<div class="outer">
<div class="inner">
<div class="title">
Autosize this section based on content
</div>
<div class="rightside">
Right align this
</div>
</div>
</div>
you should use flexbox or grid to solve this kind of problems its easy and fast
flex example
.outer {
width:500px;
border:1px solid red;
}
.inner {
display:flex;
flex-direction:row;
justify-content:space-between;
}
.outer div {
/* display:inline-block; */
border:1px solid green;
}
.rightside {
width:auto;
text-align: right;
}
<div class="outer">
<div class="inner">
<div class="title">
Autosize this section based on content
</div>
<div class="rightside">
Right align this
</div>
</div>
</div>
and grid
.outer {
width:500px;
border:1px solid red;
}
.inner {
display:grid;
grid-template-columns: auto auto;
grid-template-rows: auto;
justify-content:space-between;
}
.outer div {
/* display:inline-block; */
border:1px solid green;
}
.rightside {
width:auto;
text-align: right;
}
<div class="outer">
<div class="inner">
<div class="title">
Autosize this section based on content
</div>
<div class="rightside">
Right align this
</div>
</div>
</div>
Flexbox will help!
.outer {
width: 500px;
border: 1px solid red;
}
.outer .title,
.outer .rightside {
display: inline-block;
border: 1px solid green;
}
.inner {
width: 100%;
display: flex;
justify-content: space-between;
}
<div class="outer">
<div class="inner">
<div class="title">
Autosize this section based on content
</div>
<div class="rightside">
Right align this
</div>
</div>
</div>
If you would like the rightside to fill the rest of the space, you could use flexbox and flex-grow, like this:
.inner {
display: flex;
justify-content: space-between;
}
.inner div {
display:inline-block;
border:1px solid green;
width: auto;
flex-grow: 1;
}
.rightside {
width:auto;
text-align: right;
}
With flexbox, you only need to set display: felx; for the parent element, and margin-left: auto; for the rightside (child) element :
div {
border: 2px dotted silver;
padding: .5em;
}
/* ---------------- */
.parent {
display: flex;
}
.rightside {
margin-left: auto;
}
<div class="parent">
<div>
Child 1
</div>
<div class="rightside">
Child 2
</div>
</div>
I am trying to achieve this layout.
left column fixed size
right column fluid, it may have x number of elements inside, for example up to 4 divs 50px wide (this is done dynamically) so it must be max 200px wide, or if it has 3 such elements, then it must be 150px wide...
center column fluid, takes all the rest space
The closest I have comes is this:
#container {
overflow:hidden;
width: 100%;
}
#leftcol {
border: 1px solid #0f0;
float: left;
width: 80px;
}
#rightcol {
border: 1px solid #0f0;
float: right;
}
#centercol {
border: 1px solid #000;
margin-left: 80px;
}
.box{
width:50px;
height:20px;
background:red;
float:left;
}
<div id="container">
<div id="leftcol">
fixed 80px
</div>
<div id="rightcol">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
<div id="centercol">
fluid center
</div>
</div>
but center fluid is not correct width.
I can change some html if it will be easier to achieve desired effect.
You can do it with the Flexbox:
body {margin: 0}
#container {
display: flex; /* displays flex-items (children) inline */
overflow: hidden;
}
#leftcol {
border: 1px solid #0f0;
width: 80px;
}
#centercol {
flex: 1; /* takes the remaining horizontal space */
border: 1px solid #000;
}
#rightcol {
display: flex;
border: 1px solid #0f0;
max-width: 200px; /* adjust to your needs */
}
.box {
width: 50px;
height: 20px;
background: red;
}
<div id="container">
<div id="leftcol">
fixed 80px
</div>
<div id="centercol">
fluid center
</div>
<div id="rightcol">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>
I have an outer DIV (4) and three inner DIVs (1-3). I don't care about width here. It's all about height and vertical centering. I want the outer DIV (4) to get the height of the highest inner DIV (2 in row A). More importantly I want the other inner DIVs (1 and 3 in row A) to get centered vertically (in relation to the height of the outer DIV that has the same height as the highest inner DIV).
The contents of the DIVs are dynamic (compare row A and B) therefore I don't know which inner DIV will be the highest. Until now I used a jQuery solution that set the margin-top of the smaller DIVs (red marks) but I would like to solve it in plain CSS now.
This is easy using a flexbox - the property align-items: center produces the desired result - see a demo below:
.wrapper {
display: flex;
justify-content: center;
align-items: center;
border: 1px solid red;
}
.wrapper > div {
border: 1px solid;
}
<div class="wrapper">
<div class="one">Some text here</div>
<div class="two">
There is a lot of text here
<br>There is a lot of text here
<br>There is a lot of text here
<br>
</div>
<div class="three">Some
<br>text</div>
</div>
.outera {
border:solid 1px #333;
}
.outera div {
width:20px;
border-radius: 16px;
background-color:#212121;
margin:10px;
display:inline-block;
vertical-align: middle;
}
.outera .a1 {
height:20px;
}
.outera .a2 {
height:80px;
}
.outera .a3 {
height:50px;
}
<div class='outera'>
<div class='a1'></div>
<div class='a2'></div>
<div class='a3'></div>
</div>
You can use CSS Flexbox.
In the below snippet I've used display: inline-flex;. Have a look at the snippet below:
body {
padding: 20px;
}
.outer {
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid #000;
}
.inner {}
.a .element {
width: 20px;
height: 20px;
border-radius: 50%;
background: red;
}
.b .element {
width: 20px;
height: 50px;
border-radius: 50%;
background: green;
}
.c .element {
width: 20px;
height: 30px;
border-radius: 50%;
background: blue;
}
<div class="outer">
<div class="inner a">
<div class="element"></div>
</div>
<div class="inner b">
<div class="element"></div>
</div>
<div class="inner c">
<div class="element"></div>
</div>
</div>
Hope this helps!
body {
position: relative;
}
.test {
position: absolute;
top: 10px;
left: 10px;
height: 200px;
border: 1px solid #ccc;
overflow-y: auto;
overflow-x: hidden;
white-space: nowrap;
}
.wrap {
display: inline-block;
}
.item {
padding: 10px;
border-bottom: 1px solid #ccc;
}
.item:last-child {
border-bottom: none;
}
<div class="test">
<div class="wrap">
<div class="item">Some</div>
<div class="item">Larger amount</div>
<div class="item">of text</div>
<div class="item">should go in</div>
<div class="item">these items to prove</div>
<div class="item">that this thing is gonna grow to whatever</div>
<div class="item">to whatever</div>
<div class="item">it needs to</div>
</div>
</div>
The problem is that when the vertical scroll bar appears the absolutely positioned div doesn't grow accordingly and some content on the longest item is cut off. If I take 'overflow-x: hidden' off a horizontal scroll bar appears and that's not what I want either.
When 'white-space: nowrap' is removed everything looks good but I want each item to be one line. Is there any way to have the absolutely positioned div grow according to the width of a 'white-space: nowrap' element?
I think this is what you want
body {
position: relative;
}
.test {
position: absolute;
top: 10px;
left: 10px;
height: 200px;
border: 1px solid #ccc;
overflow-y: auto;
overflow-x: hidden;
white-space: nowrap;
}
.wrap {
display: inline-block;
}
.item {
padding: 10px;
border-bottom: 1px solid #ccc;
padding-right:28px;
}
.item:last-child {
border-bottom: none;
}
<div class="test">
<div class="wrap">
<div class="item">Some</div>
<div class="item">Larger amount</div>
<div class="item">of text</div>
<div class="item">should go in</div>
<div class="item">these items to prove</div>
<div class="item">that this thing is gonna grow to whatever</div>
<div class="item">to whatever</div>
<div class="item">it needs to</div>
</div>
</div>
I added padding-right:28px; to accommodate for the width of the existing padding and the width of the scrollbar.
I cant seem to be able to do this with relative and absolute positioning like I have with other things, but what I want to achieve is to have a div, with another div within it, however this inner div must appear outside the outer div on screen.
<div class="OuterDiv">
<span>Other things</span>
<div class="InnerDiv">
<span>Inner content</span>
</div>
</div>
EDIT : OK, so this I think is more complex than people are thinking. Using position relative and absolute I have already gotten other things on my page to work. What I have when I try this problem using positioning is
And then disappears completely when moved far enough outside of the outer div
More of my code,
<div class="Item Menu Active" style="display: inline-block;">
<div class="ItemList" style="left: -315.859375px;">
<div class="Item" style="display: inline-block;">
<span>N</span>
<div class="ItemList">
</div>
</div>
<div class="Item" style="display: inline-block;">
<span>O</span>
<div class="ItemList">
</div>
</div>
<div class="Item" style="display: inline-block;">
<span>P</span>
<div class="ItemList">
<div class="Item ClickItem">
<span>p1</span>
<div class="ItemList">
</div>
</div>
</div>
</div>
<div class="Item" style="display: inline-block;">
<span>Q</span>
<div class="ItemList">
</div>
</div>
</div>
</div>
.Item {
display: inline-block;
position: relative;
white-space: nowrap;
padding: 5px 10px 5px 10px;
cursor: pointer;
}
.ItemList {
display: none;
z-index: 1;
min-width: 75px;
position: absolute;
top: 100%;
left: 0px;
overflow-y: scroll;
overflow-x: hidden;
white-space: initial;
padding: 5px 5px 5px 5px;
background-color: white;
border: 1px solid black;
cursor: default;
}
EDIT 2 : Yes overflow:visible was my problem, issue is that overwrites the overflow-x and overflow-y that I am already using on the .ItemList for vertical scrolling on smaller screens. Any further suggestions?
You could position absolutely the inner div with the respect to the body as follows:
* { box-sizing: border-box; }
html {
height: 100% }
body {
position: relative;
padding: 10px;
min-height: 100%;
margin: 0;
border: 10px solid red; }
.OuterDiv {
width: 50%;
border: 10px solid green; }
.InnerDiv {
position: absolute;
width: 20%;
right: 10px;
border: 10px solid blue; }
<div class="OuterDiv">
<span>Other things</span>
<div class="InnerDiv">
<span>Inner content</span>
</div>
</div>
Note that in this case you must ensure that the body is high enough to contain the absolutely positioned inner div.
I feel like you shouldn't be structuring your HTML this way if this is the desired result: why not just have the inner div placed outside the parent's hierarchy? Either way, something like this should work:
<body>
<div id="outer">
<div id="inner">
</div>
</div>
</body>
And CSS
#body
{
position:relative;
}
#inner
{
position:absolute;
right:0;
top:30px;
}
You need to use position rule to set your elements to display within each-other.
#Outer {
position: relative;
width: 300px;
height: 180px;
border: 3px solid red;
}
#Inner {
position: absolute;
width: 50%;
height: 50%;
border: 3px solid blue;
margin: 5%;
}
<div id="Outer">
<div id="Inner"></div>
</div>
Try this out :
.OuterDiv{ position:relative; width:80px; height:80px; border:5px solid green }
.InnerDiv{ position:absolute; top:0; right:-100px; width:80px; height:80px; border:5px solid red }
<div class="OuterDiv">
<span>Other things</span>
<div class="InnerDiv">
<span>Inner content</span>
</div>
</div>
Edit:
It disappears because of overflow-x: hidden;
Previous:
http://jsfiddle.net/1k1rfrn3/
You should avoid hacking your DOM with CSS.
.OuterDiv{
border-style: solid;
border-width: 5px;
color: blue;
position:absolute;
overflow: visible;
}
.InnerDiv{
border-style: solid;
border-width: 5px;
color:red;
position:absolute;
left:500px;
}