I use padding and a negative text-indent to create an indented layout for responsive forms but now want to make the bottom paragraph a block level element so it always wraps.
The layout works fine when the bottom row is display inline or inline-block but as soon as the bottom row is display block then the entire layout in Chrome changes.
I don't know which browser is right, but it is Firefox's interpretation of the layout that I am after.
This is a simplified version of a layout I use for forms to attempt to fix this problem.
http://codepen.io/rachelreveley/pen/rxxxRj
<div>
<div>
<p class="top">Lorem ipsum dolor sit amet</p>
<p class="bottom">Lorem ipsum dolor sit amet</p>
</div>
</div>
<style type="text/css">
div div {padding-left: 36%; margin: 0; text-indent: -18%; background-color: #cee; width: 300px;}
p {text-indent: 0;}
p.top {display: inline-block; background-color: #ffc;}
p.bottom {display: block; width: 200px; background-color: #fcf;}
</style>
Real world example of how this code is being used.
I have fixed this by changing from using padding to margin on the parent container and then adjusting the sizes after that.
Related
I’ve noticed some unexpected layout behaviour of flex content, namely it affects positioning of the unrelated elements on the page.
Scenario: I have div.container and div.content inside. div.container has the display set to inline-flex and centres div.content vertically.
Now, any content (that uses regular flow) I put after the container can’t go higher than the top of div.content.
When I add some free text after the div.container, it is aligned with the div.content top, even though it is completely outside the flex container and should be unrelated to it.
When I add another div.container, it is positioned the way its div.content is no higher that div.content of the previous, unrelated div.container. This container (or rather its div.content) in turn affects the position of the subsequent ones.
https://flex-content-affects-outside.stackblitz.io/
It looks as if the top of a div cannot be placed higher than the top of divs before it in the document flow.
In my case, this doesn’t affect inline-flex containers directly, but rather their content. The vertical position of the flex containers if affected as the result – so that their content is aligned.
This behaviour is visible in Chrome and IE11. On the other hand, in Firefox everything works as expected.
My question is: What causes such a behaviour? Is it in any way standardized?
In the example above isn’t a significant problem, we can wrap all the boxes in another flex to get the expected behaviour. However, I’m afraid that in more complex layouts some unexpected relations between seemingly independent content can ruin the layout.
Edit: I'm adding a code snippet.
.container {
font-size: 30px;
margin: 10px;
width: 200px;
height: 200px;
border: 1px solid #888;
display: inline-flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.container .content {
width: 100%;
text-align: center;
background: rgba(200, 200, 200, 0.5);
}
<div class="container">
<div class="content">
Content.
</div>
</div>
<div class="container">
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
</div>
As Paulie_D noticed in the comment, it was caused by vertical-align. Once we specify vertical-align: top everything works as expected.
.container {
font-size: 30px;
margin: 10px;
width: 200px;
height: 200px;
border: 1px solid #888;
display: inline-flex;
align-items: center;
justify-content: center;
overflow: hidden;
vertical-align: top;
}
.container .content {
width: 100%;
text-align: center;
background: rgba(200, 200, 200, 0.5);
}
<div class="container">
<div class="content">
Content.
</div>
</div>
<div class="container">
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
</div>
Or, more elaborate one:
https://stackblitz.com/edit/flex-content-affects-outside-baseline-elwwvc?file=style.scss
More precisely, the layout was due to the implicit vertical-align:baseline (in Chrome and IE). The boxes are inline-flex and there were laid out according to the baseline. Once we specify this explicitly the behaviour is consistent among browsers. Another font size in one of the boxes makes it more visible.
https://stackblitz.com/edit/flex-content-affects-outside-baseline?file=style.scss
In this example I'm using flex-direction:row
http://jsfiddle.net/9a1d2ddz/
When space is not enough to fit elements, a vertical scrollbar appears
I want to achieve the same, but with "top to bottom" box ordering
http://jsfiddle.net/ebd8rsnx/
but instead of getting an horizontal scrollbar I want to keep the vertical one
basically the same of the above, but with top to bottom box ordering instead of left to right
I thought it was something I could do with max-height:min-content but it seems to have no effect.
thank you in advance
div
{
overflow:auto;
border:2px blue solid;
box-sizing:border-box;
flex-direction:column; /* try column|row */
display:flex;
flex-wrap:wrap;
}
span
{
min-width:150px;
min-height:150px;
flex:1 1 auto;
border:1px red solid;
display:block;
overflow:hidden;
box-sizing:border-box;
}
I tried specifying the overflow direction, but that doesn't seem to work in this case. I think the problem is that you're trying to make your overflow direction as your wrap direction.
for example, try making it do the same type of thing horizontally. It'll create the same problem because you are attempting to flow and overflow in the same direction. That said, I don't think you'll be able to do what you want with straight css. You may want to consider a js tool like Columnizer or Masonry. The reason being that it can't just flow. It needs to calculate the columns first, then adjust the elements to fill in the columns before it determines its content length in the overflow direction. With a flow, there's no way for a browser to determine when it should break to a new row/column if your overflow is in the same direction as your flow. I've made something like this work before, working horizontal, but the way it worked was to put everything into 1 row, which isn't what you're really going for here.
CSS3 "column" feature works well for me:
http://caniuse.com/#feat=multicolumn
The column content can be anything, not text-only. Set column-width on the div containing the content, and wrap it into another div with fixed height.
.columns-container {
max-height: 50vh;
overflow-y:auto;
}
.columns {
-webkit-column-width: 15em;
-moz-column-width: 15em;
column-width: 15em;
/*optional column-count*/
/*
-webkit-column-count:4;
-moz-column-count: 4;
column-count: 4;
*/
-webkit-column-gap: 0;
-moz-column-gap: 0;
column-gap: 0;
}
<div class="columns-container">
<div class="columns">
<div>Lorem ipsum dolor sit amet. Sample text 1</div>
<div>Lorem ipsum dolor sit amet. Sample text 2</div>
...
<div>Lorem ipsum dolor sit amet. Sample text 1000</div>
</div>
</div>
How can I constrain the width of a child within an inline-block element?
Assume that I am targeting newest browsers.
Given an element displayed using inline-block, how can I constrain a child element so that it does not scale beyond the parent's witch.
In practical terms, I am trying to built a system that will take an image of any width and keep the caption constrained to the width of the parent container:
without having to specify width
without using jQuery or other DOM manipulation
CSS
<style>
div {
width:800px;
background-color:silver;
text-align: center;
}
figure {
display:inline-block;
background-color: orange;
padding: 1em;
margin: 0;
}
figcaption {
background-color:pink;
}
</style>
HTML
<div>
<figure>
<img src="http://i.techrepublic.com.com/blogs/11062012figure_a.gif" />
<figcaption>
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
</figcaption>
</figure>
</div>
In my opinion adding the following code can help you:
figure {width: 100%;}
img {width: 100%;}
In any case if you want to do this only with CSS, then you need play with percentages.
For a good long while I've been using a really nice column spanning method I stumbled across, wherein I can have a div with the class .boxcontainer and child .box elements, and using an :after pseudo-element on .boxcontainer, my .box columns justify nice and evenly across the page. Here are the all-important definitions:
.boxcontainer {
text-align: justify;
-ms-text-justify: distribute-all-lines;
text-justify: distribute-all-lines;
background-color: orange;
}
.boxcontainer:after {
content: '';
display: inline-block;
width: 100%;
height: 0px;
font-size: 0px;
line-height: 0px;
}
Most of my previous projects have been XHTML1 Transitional (which I have subsequently learned uses a limited quirks mode when compared to other DTDs), and using this method in XHTML1 the parent .boxcontainer always wrapped perfectly flush around the child .box elements.
However, working on a new project in HTML5, I've discovered that there appears to be an extra line added underneath the justified .box elements. You can see an example here: http://jsfiddle.net/RZQTM/1/ - click on Fiddle Options and change the DTD to just about anything else and you'll see what I mean - an orange 'band' appears underneath the justified blue boxes.
I think this is down to something in the :after pseudo-element being rendered almost like an additional line of content, but I have no idea how to fix it. Any tips on how to remove the extra space under the boxes would be most gratefully received.
The trick i use to make this extra line to vanish is to apply line-height:0; on parent ,
and reset line-height to 1.2em or whatever line-hight you had setted.
vertical-align:top;/* or bottom */ on :after elements ends up to swallow any vertical gaps left.
one exemple : http://codepen.io/gcyrillus/pen/dlvCp
A work around with extra markup and using CSS table-cells
I sometimes use the following. In the HTML, I add an extra element div.spacer:
<div class="boxcontainer">
<div class="box two">
<h3>This is the title</h3>
Lorem ipsum dolor amit ...</div>
<div class="spacer"></div>
<div class="box two">
<h3>This is the title</h3>
Lorem ipsum dolor amit ...</div>
<div class="spacer"></div>
<div class="box two">
<h3>This is the title</h3>
Lorem ipsum dolor amit ...</div>
<div class="spacer"></div>
<div class="box two">
<h3>This is the title</h3>
Lorem ipsum dolor amit ...</div>
</div>
For the CSS, I use display: table on the parent container and then display: table-cell on the .box child elements:
.boxcontainer {
background-color: orange;
display: table;
width: 100%;
}
.box {
vertical-align: top;
display: table-cell;
background-color: blue;
color: white;
font-family: Trebuchet MS;
}
The demo fiddle is: http://jsfiddle.net/audetwebdesign/xWfk2/
Internally, the CSS re-purposes the .spacer as sibling table-cells and the default spacing tends to be even because the .box elements have a fixed width.
This approach is ideal if the .spacer elements serve a useful purpose (have real content) and if you have other reasons to use table-cells, say vertical positioning control and so on.
I'm not really sure how to best explain this. I'm trying to have three div elements positioned side-by-side; the first (left to right) is flexible-width, the second is also flexible width, the third is static width and it floated to the right. The first two are inside a div on the same level as the third; that is to keep to total width of the first two under a max-width.
Here is a jsfiddle of what I'm doing.
My problem is that when the text in the middle div is long, the middle div will drop below the first one, instead of having the text wrap. I can't give the middle one a max-width, because the first div is flexible and could get smaller. Any idea how I can go about fixing this?
I know it can be achieved by using a table, but I'd really prefer not doing so unless it's the only easy solution.
Edit: I decided to just do fixed width. The amount of work for required for this just wasn't worth it, especially considering that most of the time, the flexible width would never be used for me anyway.
if you wan a pure css based solution then it might be little difficult and also not much browser compatible. Though you can achieve this by using the css property called display:table ; and display:table-cell;. Again older browser, maybe IE-9 also won;t be able t render this.
Then you should go for the jQuery solution. You can use the following code-
$(document).ready(function(){
var w = 400 - $('.inner_container .left_box').width();
$('.inner_container .middle')css('width',w);
});
Thanks.
The display: table property and related properties, such as display: table-cell, have been supported in IE since version 8 -- as well as all versions of Firefox and Chrome/Safari.
Reference: http://caniuse.com/#feat=css-table
I believe it's the way to go in your case.
HTML
<div class="container">
<div class="inner_container">
<div class="left_box">
<p>Lorem ipsum dolor sit amet</p>
</div>
<div class="middle">
<p>Lorem ipsum dolor sit amet</p>
</div>
</div>
<div class="right_static">Hi!</div>
</div>
CSS
.container {
position: relative;
width: 500px;
border: 1px solid #000;
overflow: auto;
}
.right_static {
position: absolute;
top: 0px;
right: 0px;
width: 100px;
background-color: green;
}
.inner_container {
display: table;
width: 400px;
overflow: auto;
}
.left_box {
display: table-cell;
background-color: red;
}
.middle {
display: table-cell;
background-color: #9999FF;
}
DEMO
http://jsfiddle.net/nd7qj/
By the way, you mentioned in your question that the leftmost div should have flexible width, but in the CSS you provided it had fixed width. So I didn't apply a width to it in my code.