Is it possible to evenly space many elements in a div with changeable width.
Here's not working example. If we use text-align:center; elements will be centered, but margin:0 auto; is not working. I want to accomplish something like justify+center:
|..<elem>..<elem>..<elem>..<elem>..| // for one container width
|..<elem>..<elem>..<elem>..| // for smaller container width
|....<elem>....<elem>....| // even smaller container
Container will be user resizable.
One picture is worth a 1000 words:
Container(red box) width:100%; So user can resize it (browser window, js, whatever).
<--> represent even spaces.
In second row <--> are bigger because there is more room. I was able to fake it with:
text-align:center;
word-spacing:3em; // but any fixed value looses proportion
I recently read about a very clever technique to do exactly what you're asking.
In short, you just need to use text-align:justify; on the container element to achieve this, in conjunction with an extra invisible block at the end.
This works because inline-block elements are seen as being part of the text content, each being effectively a single word.
Using justify will spread out the words in your text so that they fill the entire width of the element with extra space between the words. For inline-block elements, this means that they are spaced out with even spaces between them.
I mentioned an extra invisible block at the end. This is required because normal text-align:justify won't justify the last line of text. For normal text, that's exactly what you want, but for aligning inline-block boxes, you want them all to be aligned.
The solution is to add an extra invisible but 100% width element to the end of your list of inline-block elements. This will become effectively the last line of text, and thus the justify technique will work for the rest of your blocks.
You can use the :after pseudo-selector to create the invisible element without needing to modify your markup.
Here's an updated version of your jsFiddle to demonstrate: http://jsfiddle.net/ULQwf/298/
And here's the original article that explains it in more detail: http://www.barrelny.com/blog/text-align-justify-and-rwd/
[EDIT]
One final update after seeing the image you've added to the question. (I don't have a better answer, but some additional thoughts that might be useful).
Ideally what you need here is a :last-line selector. Then you could text-align:justify the main text and text-align:center the last line. That would do what you want.
Sadly, :last-line isn't a valid selector (:first-line is, but not :last-line), so that's the end of that idea.
A slightly more hopeful thought is text-align-last, which does exist as a feature. This could do exactly what you want:
text-align:justify;
text-align-last:center;
Perfect.
Except that it's non-standard and has very limited browser support.
You can read about here on MDN.
I guess as a last resort it might be an option for you, if you can live with only partial browser support. It would at least get what you want for some of your users. But that's not really a sensible way to go.
My gut feeling though is that this as as close as you're going to get. Tantalisingly close to what you want, but just not quite there. I hope I'm proved wrong, but I'll be surprised. Too bad though, because I it would seem like a perfectly logical thing to want to do.
I worked on your example, you have to make a combination of block / inline style since the justify alone just work for inline (text).
div{
width:530px; /* I changed the div size, because you a have fixed width otherwise you should use scrolling */
border:1px red solid;
text-align:justify; /* You will justify to 100$ of containing div, if you want to "center" just add another div with % size and centered */
}
div span{ /* I worked with your example you may use a class */
width:60px;
border:1px yellow solid;
display: inline-block; /* Inline-block */
position: relative; /* relative to container div*/
}
div:before{
content: ''; /* position for block element*/
display: block; /* the block part for the last item*/
width: 100%;
}
div:after {
content: '';
display: inline-block; /* inline-block for the first (and middle elements) */
width: 100%;
}
If tried a different approach, in the fiddle looks pretty similiar to the picture but the space is fixed in both lines but the elements are intercalated.
div{
width:250px; /* I changed the div size, because you a have fixed width otherwise you should use scrolling */
border:1px red solid;
text-align:center; /* You will justify to 100$ of containing div, if you want to "center" just add another div with % size and centered */
}
div span{ /* I worked with your example you may use a class */
width:60px;
float:justify;
border:1px yellow solid;
display: inline-block; /* Inline-block */
margin-left:2%;
margin-right:2%;
}
Related
I have a layout, where I have to make a vertical centeret, with a rotated text inside.
See fiddle: http://jsfiddle.net/C7mCc/3/
I use display:table; and display:table-cell; to make the vertical centering, which is working good.
The HTML
<div id="top-banner-advertising-text" class="v-center">
<p class="v-c-content">Annonce</p>
</div>
and the CSS
.v-center {
display: table;
}
.v-center .v-c-content {
display: table-cell;
vertical-align: middle;
}
But I only want the #top-banner-advertising-text to have a width of 15px. Like in this fiddle: http://jsfiddle.net/C7mCc/4/ where I have removed the .v-center and .v-c-content and therefore do not have the text vertical centered.
How can I control the width of the div?
This ended up being a lot more complicated than I expected. To control the width you must take into consideration your parent divs. There is an excellent explanation of this here:
100% height block with vertical text
Although this in order to help you out I went ahead and figured out how to switch this code up to swap the text to the other side of the img for you.
my jsfiddle:
http://jsfiddle.net/C7mCc/6/
To answer your questions, "How do I control the width".
This is done by taking the following lines in the css and making sure they match,
padding-left:2em; /* line-height of .wrapper div:first-child span */
width:2em; /* line-height of .wrapper div:first-child span */
height:2em; /* line-height of .wrapper div:first-child span */
line-height:2em; /* Copy to other locations */
Remember since your vertical now you must think about the padding left.
basically your line height padding left width and height come in to play.
We control them with em in order to make sure they are sized correctly.
Let me know if you need anymore help.
Sounds like you're looking for the not selector:
/* if it must not have the vertical centering class */
#top-banner-advertising-text:not(.v-center) {
width: 15px;
}
http://jsfiddle.net/C7mCc/5/
Alternately, you could leave the width as you have it in your 2nd example and add this:
#top-banner-advertising-text.v-center {
width: auto;
}
to set a width for an element displayed as table, you use : table-layout:fixed;
But you do not say that you want as well to rotate a text.
To rotate that text, you will need white-space:nowrap if more than one word (15px is really small).
to replace that text in middle, you will need translate(); and set that text in a container displayed as a table, so it expands over 15px and makes translate usable.
here an example with 2 version rotated 90 and -90 degres : http://codepen.io/gc-nomade/pen/JuAio.
For older IE, search for the old writing-mode http://msdn.microsoft.com/en-us/library/ie/ms531187%28v=vs.85%29.aspx ;) .
I need DIV blocks which have some data. Due to different content, blocks have variable height. I need to align div blocks by two. Because of the different height of blocks there is "free space" remaining. How to align these blocks so it would be aligned properly?
The data comes from JSON reques so making table seems : 1. more tricky to make grid using JS (2 elements in a row) 2. Obsolete (?) . What would you recommend?
CSS:
.book-details{
float:left;
display:block;
border-style:solid;
border-width:1px;
padding: 2px 2px 2px 2px;
border-color:gray;
width: 450px;
display: table;
}
PIC:
IE7 and below doesn't get display:table, for IE8, you have to use the html5 doctype, ie 9 will work.
Better to avoid it and just float. Remember your box model. Your width is actually 456px so what's the parents' width?
And, you should clear the float after two if you're just doing 2x across.
You could just set a height that will be tall enough for the longest div. What you're pulling in seems to be easy enough to estimate.
I have a div with display:block in my css. This div block uses the align = "absmiddle" . It displays all the elements in 1 line in Chrome. However, in firefox, the elements are displyed on to the next line as well. How do I get them to display in 1 single line in firefox.
P.S: I have already tried display: inline but it does not bring it in 1 line.
<div class="one"><input name="elementone" value="1" align="absmiddle" class="subone" /></div>
Css is
div.one,div.subone{
display:block;
width:16px;
height:100%;
background-position:0 0px;
border:0
}
I'm a little unclear on what you're trying to accomplish - centering input elements in a div?
All you need is a text-align: center on container div that holds all the inputs [.one is the class that should have center text alignment in the case of your example html].
Note there are some issues with your css
div.one,div.subone{ /*div.subone refers to a div with the class subone - not an input like you have*/
display:block; /*divs are already block elements */
width:16px; /* may be the issue, why restrict the width? */
height:100%; /*basically meaningless */
background-position:0 0px; /*default*/
border:0
}
***Note: generally when you are trying to wrap a bunch of inline elements like inputs each inside their own div, there is another way to skin that cat. For instance, in this case if you have a number of divs with the class .one - they will show up on their own line because your css requires each div to display block.
I don't really understand your question but if you want multiple <div class="one"> in one line just float them left or right. However they will still jump to second line once the container div width is exceded. You could try and use a combination of white-space and overflow on the parent div.
But as I say - your problem is quite unclear from the question.
I'm trying to understand CSS positioning and I'm having trouble figuring out why a simple change that apparently should have no effect on the layout is causing a very disruptive change. I'm obviously missing something.
The initial objective was to place an inner div
vertically and horizontally within another div. That was fairly simple:
html, body {
margin:0;
padding:0;
height:100%;
}
div#container {
position:relative;
background:#4444ff;
margin: 0 auto; /* center, not in IE5 */
height:80%;
min-height:80%;
}
div#childDiv {
position:absolute;
background:#ff5555;
/* next we center it vertically and horizontally */
width:900px;
height:600px;
top:50%;
margin-top:-300px;
left:50%;
margin-left:-450px;
}
...and in the HTML page I used:
<body>
<div id=container>
<div id=childDiv>
test
</div>
</div>
</body>
which worked fine.
The curious part is what happens when I change the position attribute of the #childDiv div from absolute to relative.
My understanding is that first is should not affect the #container div at all since I'm changing only the position of the child element, and second that it should not change the layout since it is the only child element, its parent uses relative position and third I have not specified any offsets (tp, left, etc).
Instead, when I make this change, the parent #container is messed up (shows only up to the half of the viewport instead of 80% height as previously), and the position of #childDiv changes accordingly (also upwards, half outside the viewport).
My questions is: why does that happen? What concepts I'm not taking into account and why was the parent div affected by a change in the children's position setting?
If I remove #childDiv from within #container and place it inside body, then #container is no longer affected by that change so it seems something is propagating up in the DOM, which is odd to me. I've seen the same in firefox, opera, IE and chrome.
I have read W3C's spec on this topic but I haven't been able to figure this one out so far...
UPDATE: I created examples in JS fiddle to show the problem. You can see the original is here: jsfiddle.net/7Pr9y/1 and the affected one is here: jsfiddle.net/7Pr9y/3
Thank you!
Eduardo
When something is absolutely positioned, it is taken out of normal flow so its size, margins, etc. do not affect the things around it.
When something is relatively positioned, it is placed in normal flow (so its size, margins, etc. do affect the things around it) and layout is initially handled as if it were position: static, then it is moved according to the left, right, top and bottom properties.
It looks like your CSS got complex quickly because as soon as you positioned the child div absolutely, your container div would have disappeared, and putting percentage-based widths and heights on it wouldn't work.
The reason for this is that once you position something absolutely, it's taken out of the document flow, so your container div is now acting as if it contains nothing. If it contains nothing, unless you give it absolute dimensions (say, in pixels), you're saying "size yourself to a certain percentage of your container", which in this case, is the body element, which also acts as if it contains nothing.
When you start tossing heights and widths and min-heights on every element to compensate, especially when they are relative values, the results can become unpredictable very quickly. My advice would be to check out this reference on the box model by Chris Coyier: http://css-tricks.com/the-css-box-model/
It's super straightforward and uses some great diagrams to help visualize the different aspects of CSS positioning.
OK, I figured out why it becomes smaller when I change the size to relative.
Happens that because I have set the margins of the #childDiv to a negative value in order to center it, when I change it to relative that negative margin is taken into account when calculating the height of #container, resulting in a smaller #container.
I'm obviously a beginner in this, but seriously, it looks like CSS made it as complicated as possible to lay things out. No surprise most folks coming from table layouts start frustrated. :(
You don't need all these negative margin settings. Do the following:
html, body {
margin:0;
padding:0;
height:100%;
}
div#container {
background:#4444ff;
margin: 0 auto; /* center, not in IE5 */
text-align: center;
height:80%;
min-height:80%;
}
div#container:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em; /* Adjusts for spacing */
}
div#childDiv {
display: inline-block;
text-align: left;
vertical-align: middle;
background:#ff5555;
width:500px;
height:200px;
}
I have used your code you provided and changed it around a little, to make the ghost spacer (the div#container:before) work.
I have a few divs which makes a little bit too spacey between the footer and the body. So i want to convert one div to a span. But when I do that, it messes the footer's content a bit up.
How can i do this and keep the styles that already have been defined for the footer?
Thanks in advance!
Edit
div.footer {
width: 986px;
margin: 0 auto;
padding-bottom:18px;
border: 0;
text-align: left;
color:#000000;
}
As you already know, the difference between a <div> and a <span> is just that one defaults to display:block; and the other to display:inline;. To make one act as the other, just set the display style to the other type.
However, you already said you tried this and it didn't achieve the effect you were looking for. There is another display property, which is less well known, but provides a half-way house between the two:
display:inline-block;
What it does is display it inline, but still with block-like properties. (This is basically how an <img> tag works by default).
Could this be the answer you're looking for?
To convert a div to a span, simply add:
.myDiv
{
display: inline;
}
But I'm really not sure that this is the solution you're after.
Quote:
there are 2 divs next to eachother which creates a hugh gap between the body and the footerbody and the footer
Solutions:
Remove empty div(s) from HTML
Remove empty div(s) by adding display:none
Reduce height of the div(s)
Reduce margin or padding of the div(s)
Set position:relative; top:-[yourownnumber]px to .footer
Try adding overflow:auto; to your span. Also add display:block;
If there is too much space between the footer and the body, have you looked at what the margins and paddings are on the affected divs? Does something have a height or a min-height that is making some of the content within the body taller than the natural end of the content? Firebug is a great tool for this.
Div is a block element. Other block elements are paragraphs, headings, lists, etc. Span is an inline element. Other inline elements are strong, image, anchor, etc.
You still need the body to be contained in a block-level element.
How if add this:
position:relative /*optional*/
float:left;
left:0px;
I always do this before i know to use span when I first learn css I always do to my element content.