I am trying to build a horizontal scrolling layout, composed of image blocks:
<div class="container">
<div class="item">
<img src="http://placehold.it/200x300">
</div>
<div class="item">
<img src="http://placehold.it/400x300">
</div>
<div class="item">
<img src="http://placehold.it/300x300">
</div>
</div>
I used display:inline-block and white-space: nowrap; properties to achieve this, and it does work but browsers don't seem to recompute block widths on resize?
Check here: https://jsfiddle.net/g597w3Lr/2/ and try resizing the browser..
Here is a screen grab to better understand what is my problem:
https://youtu.be/VxKo4gysc1o
At first all images are well positioned and i can scroll horizontally: perfect.
I then resize the browser
images are resizing, not the .item wrappers. White gaps appear :(
Basically i was expecting same feature as with vertical scrolling, i.e. adapting width depending on content size.
I actually dont even understand the logic here..
Is there any way to get over this?
Thanks!
Original answer
EDIT 2: Looking at your video I think the new approach is what you are looking for.
You have to display your divs with .item class as inline and remove your white-space: normal property.
.item {
display: inline;
height:100%;
}
Updated JSFiddle.
Explanation:
I am not an expert of CSS so if someone see some mistake please correct me.
When you display an element as inline-block as the official documentation says:
inline-block
Causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.
which means that the element that you display as inline-block acts like a block but you can set it inline (in the same line). This means that you can set a div (which is display: block as default) in a single line. You can also see it here:
The div element, short for division, is the block level generic container.
Also, inline elements cannot get height/width properties so this is the reason why when you display your divs with .item class as inline, they wrap the content but not get the height/width that they should correspond to take (from their parents in your case, as you put them with %).
If you display them as inline-block it does not changes anything about their default height/width properties. Just allows you to display them in a single line.
JSFiddle to see the three divs (inline/ inline-block / block, as default).
You will have to modify slightly your css
HTML
<div class="container">
<div class="item">
<img src="http://placehold.it/200x300">
</div>
<div class="item">
<img src="http://placehold.it/400x300">
</div>
<div class="item">
<img src="http://placehold.it/300x300">
</div>
</div>
CSS
html,body {
height:auto;
}
.container {
display: inline-block;
white-space: nowrap;
height:auto;
}
.item {
display: inline-block;
white-space: normal;
}
.item img {
width:100%;
height:100%;
}
Fiddle
check it see that's what you want ?
I manage your classes with border:solid 1px red;
and use width:100% in some classes.
also in class item:
width:100%;
https://jsfiddle.net/g597w3Lr/6/
Related
I have a parent container that has a (priori unknown) number of children that have a minimum width. When I resize the browser past the point of children shrinking, the parent background shrinks with the window, and does not cover children.
.row{
display:flex;
background-color:#fcc;
background-size:cover;
}
.row:nth-child(odd){
background-color:#fbb;
}
.child{
min-width:150px;
border:1px #ccc solid;
flex-grow:1;
}
<div class="row">
<div class="child"> content </div>
<div class="child"> content </div>
<div class="child"> content </div>
</div>
<!--more rows follow-->
jsfiddle
How would I go about ensuring the parent background covers all the children?
I tried putting width:100%, background-size:cover on the .row element. Also tried wrapping everything in a container and setting overflow:auto on that.
The only way I can sort of get it work is if i put overflow:auto on the .row element, but then it makes each row horizontally-scrollable independent of others.
I already saw this post, but it's not exactly what I need - I'm not wrapping any flex-items, the point is for them to stay the way they are.
I also read this article, but I can't see anything that can help with my problem.
You probably want display: inline-flex;
Check: https://jsfiddle.net/n5s3n3g8/1/
I still have problem to well understand how the float property works in CSS. I do apologize because I know this is css basics but I really want to understand that and get a good explanation. I've created an example to show you.
Here is my page :
I just want to resize the second div at the right. When I look at it in the Chrome Developer Tools, I see that this div begins at the top left of the window and not after the red square. I'd like it to begins just after the red square to change the width properly without calculating the size of the square and doing something like
width = square size + width i want
Do you know how this it happens and how to properly resize the width of the second div ?
EDIT: the solution consists in add the float property to the second div too. The explanation is the following : floated elements are removed from the flow, so they don't stack with the non-floated elements.
You need to set float for another div too.
We generally do like below:
html
<div class="float-left">
<p>floated left</p>
</div>
<div class="float-left"><!--- to float next to previous div--->
<p>floated left</p>
</div>
css
.float-left{
float: left;
}
As per your comment:
We do clear the float values because the container contents would never been collapsed.
You need to float the second div.
Heres an example.
<div class="parent-div">
<div class="left">
</div>
<div class="left">
<p>This is the description of the image</p>
</div>
</div>
You need to set
p { display:inline; }
or
div { display:inline; }
since paragraphs and divs are block elements.
http://www.w3.org/TR/CSS2/visuren.html#block-boxes
the reason is that floated elements are removed from the flow, so they don't stack with the non-floated elements. - therefore they don't "take up space" like before. This is why your text div starts at the top left of its container.
from MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/float
The float CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it. A floating element is one where the computed value of float is not none.
You have to set float for both DIVs
Here is the updated code:
HTML:
<div id="main_container">
<div class="left"></div>
<div class="right">
<p>This is the description of the image <i>Random text</i>
</p>
</div>
<!--Comment below <DIV> to see the result-->
<div class="clear"></div>
</div>
CSS
#main_container {
border:5px solid #000;
}
.left, .right {
width: 100px;
height: 100px;
background: red;
float:left;
}
.right {
background: blue;
width: calc(100% - 100px);
}
.clear {
clear:both;
margin:0;
padding:0;
}
Also, just to add one more important fact related to "float" is, make sure you add "clear:both" property after "float".
Why?? Because, a common problem with float-based layouts is that the floats' container doesn't want to stretch up to accomodate the floats. If you want to add, say, a border around all floats (ie. a border around the container) you'll have to command the browsers somehow to stretch up the container all the way.
Here is the Fiddle for the same: http://jsfiddle.net/1867ud9p/7/
Hope this will help!
my html looks like this:
<div class="container">
<div class="header-content">
hello!
</div>
</div>
i've recently come into a situation where I need the 'header' to be 100% the window for a full-width background. usually i would do this css:
<div class="header-background-color">
<div class="container">
<div class="header-content">
hi!
</div>
</div>
</div>
unfortunately, i am fairly deep into a framework and can't wrap the container. i need to construct it within the container.
<div class="container">
<div class="header-background-color">
<div class="container">
<div class="header-content">
hi!
</div>
</div>
</div>
</div>
i can't figure out a way to accomplish this, and am wondering if this is possible.
if i use this css for header-background-color
background: blue;
left:0;
position: absolute;
width: 100%;
the element looks right, but the page flow is interrupted.
does anyone know if my target goal is reachable?
i made a bootply to illustrate this http://www.bootply.com/129060
You can use a child (>) selector to select the first container element and set its width to 100% and remove the padding.
.example-3 > .container {
width: 100%;
padding: 0;
}
This assumes you'll always have a wrapper around it with a unique class name (or use body if it's the first div), but this also allows you to remove the position: absolute which is causing the overlap and the height can stay dynamic.
See forked bootply: http://www.bootply.com/129065
I've added a button that inserts a paragraph into the div so you can see how it's not affected by changes in height.
Only thing I can think of is using a dumby element to maintain the vertical space (i.e. set the height), and then use absolute positioning on the full width content (as you mention). This is really ugly and won't be a good solution if the height of the content is dynamic.
See #content_dumby element in forked bootply: http://www.bootply.com/129063
OK so what would happen if I have 2 divs (one containing text, the other an image). The image always has a static width but the text varies. hence making its containing div variable.
I can make it work for all other browsers (except IE6 and IE7) by using CSS display:table. IE6 and 7 don't have that so I can't find a workable solution to center them all.
... so you know what I'm talking about...
.container{text-align:center; width:100%}
.container .centered{display:table; margin:0 auto}
<div class="container">
<div class="centered">
<div id="text">varying length text</div>
<div id="image">IMAGE</div>
</div>
</div>
Quite apart from the lack of IE support, setting display: table as you have without its children using display: table-row/table-cell results in undefined behaviour. It doesn't make sense to put block elements directly inside a table element and the browser might do anything at all.
What you are trying to do is get shrink-to-fit width behaviour without using float, which is a normal way of getting shrink-width but requires that the block in question goes to the left or right not centre. Probably a better way of saying that would be to use an inline-block:
.centered { text-align: center; }
.centered span { display: inline-block; border: dotted red 1px; }
<div class="centered">
<span id="text">varying length text</span>
</div>
<div class="centered">
<span id="image">IMAGE</span>
</div>
(You have to use a naturally-inline element like span to make it work under IE<8; div would fail. There is also -moz-inline-box if you need to target Firefox 2.)
Are you using quirksmode or standards compliant mode? In other words have you included a DOCTYPE declaration at the top of your html page?
You shouldn't need to use display:table just margin:auto should do the trick provided you are using a standards mode.
I am essentially trying to create a version of the "figure" element (upcoming in HTML5), whereby I have an image with a short description below it.
However, I want to limit the width of this entire element to that of the image, so the text isn't wider than the image (wrapping to multiple lines if necessary).
Basic HTML:
<div class="figure">
<img src="..." alt="..." width="..." height="..." /><br />
A description for the image
</div>
I'm well-versed with CSS but I can't think of any pure CSS solution, without adding a style="width:100px" to the div to match the image width.
Update: After a bit of searching and thinking, the best method seems to be using an inline width on the div. I will keep the width attribute on the image, in case I wish the div to be a bit wider than the image (for example to accomodate a longer caption).
This approach also means I could have two images side-by-side with a caption below. If I have a set of images the same size, I can of course add an extra style to each div.
Thanks to everyone who answered!
This could also be accomplished using 'display: table-caption' for the caption, as follows:
HTML
<div class="wrapper">
<img src="image.jpg" />
<div class="caption">My caption...</div>
</div>
Stylesheet
.wrapper {
display: table;
}
.caption {
display: table-caption;
caption-side: bottom;
}
This block can also be floated left of right of other text. I've tested this in IE8+. Here's a JSBin example: http://jsbin.com/xiyevovelixu/1
For setting the width to match the image automatically you could use
.figure {
display: table;
width: 1px;
}
This makes the div behave like a table (not supported in Internet Explorer). Or you could use a table instead of the div. I don't think there is another way of setting the width automatically.
Edit: The simplest way is to forget about the auto width and set it by hand. If it is really needed you can use JavaScript or a table. In this case the use of a table is not so ugly because you are addressing a limitation of the HTML version. In the case of server-side scripting you could also set the width when generating the page.
Stylesheet
div.figure img,
div.figure div.caption {
width: 100%;
}
div.figure div {
overflow: hidden;
white-space: nowrap;
}
note: to enable wrapping just remove that last css line
HTML
<div class="figure" style="width:150px;">
<img src="logo.png" alt="logo" />
<div class="caption">A description for the image</div>
</div>
I've checked it in Chrome, Firefox and IE7 and it looks good in all three. I realise this has the width on the div and not the img, but at least you only need to set the width in one place. Short of using css-expressions (IE only) I can't see a way of setting the outer divs width to the width of the first child element.
I had the same problem and after reading this decided to use an inline-style on the surrounding element. Seems the better solution over using a table to me.
You can also acheive this using the following solution proposed by Temani Afif in his blog post (All credits to him, I just don't want the solution to be forgotten)
<div class="box">
<img>
<h1>Lorem ipsum dolor ..</h1>
</div>
.box {
display: inline-block;
}
h1 {
width: 0;
min-width: 100%;
}
Make the container inline-block, and makes the h1 (or whatever text tag you use) occupy the space dictated by the sibling element. It's essentially a hack, but it works! No unintended semantic consequences like the table solutions
You could use the display:table solution for all other browsers, and a CSS Behaviour for Internet Explorer.