This is a question similar to many that have been asked before. However, with all the previous questions, the necessary widths are known. For me, the widths are unknown.
If I have two columns (primary, secondary), how would I use css such that as primary expands and contracts, secondary fills the remaining horizontal space. I would like to achieve something like the split pane effect, where the location of the split is dictated by the size of primary.
It is imperative to understand that I do not know how many pixels or how much width primary will take up, primary's size will increase and decrease.
It could be:
|----Primary----|----------------------------Secondary---------------------------|
Or:
|-----Primary------|----------------------------Secondary------------------------|
Or even:
|-------------------------Primary------------------------|-------Secondary-------|
How would I do this using CSS? Is it even possible to make an element provisionally "greedy"?
Hmmm, if you're not adverse to using it, you could apply the display:table-cell CSS property to the columns, then use width:100% on the latter one. The HTML structure would look like this:
<div class="split-pane">
<div>
Left content
</div>
<div>
Right content
</div>
</div>
And the CSS:
.split-pane > div {
display:table-cell;
}
.split-pane > div:first-child {
white-space:nowrap;
}
.split-pane > div:last-child {
width:100%;
}
Here's a JSFiddle demonstration to show you what this achieves. Note how as you add more text in a line on the left, it'll push the boundary to the right as needed. (The white-space:nowrap; is there so that the content on the left doesn't wrap on every single word.) Be advised that this CSS will not be interpreted properly on older versions of IE, if that's of concern.
If this isn't what you were looking for, let me know and I'll be happy to help further!
It is correct you can't do this with pixels, however there are other ways to define width. I think you may want to try using % rather than px in your css.
If the content of the 'sencondary' div doesn't matter, you can make some css like this:
#primary { position: absolute;
z-index: 1; }
#secondary { position: absolute;
width: 100%;
z-index: 0; }
If there is content that needs to be moved dynamically, you can move the secondary div easily with jQuery. Here's a jsfiddle with the code: http://jsfiddle.net/LZJZU/5/
Related
I made a small form that has potential to take credit-card details, as part of the Daily UI challenges (#002). I haven't implemented any functionality, just design.
Here is the form I made: http://codepen.io/alanbuchanan/pen/vGZPBp
My questions are regarding the two half-width sections of the form - Expiry Date and CC Number.
Here is the relevant code - this targets the two divs that wrap the two form elements:
div {
display: inline-block;
box-sizing: border-box;
width: 45%;
}
I wrapped these two sections in their own divs so that I could have more control over their positioning. Is it possible to position these at half-width without these wrapper divs?
In the example they are taking up 45% width because at 50%, the second div overflows onto the next line.
I just want to give it 50% and have it take up half the space as it should. Or should it not?
Even at 45% width, you can see there is about 1px difference between the height of these two divs.
After inspecting with Chrome Dev Tools, I can't find the problem behind this.
Any answers to my questions or different approaches to the situation will be very useful.
In most cases a setup as the following code, could be a best practice when aiming for creation of inline-block columns.
.column-container {
font-size:0;
line-height:0;
}
.column-container .column {
display:inline-block;
vertical-align:top;
width:50%;
font-size:16px;
line-height:120%;
}
You might wonder, why does the container have zero font-size and line-height?
This is often used because some HTML code cotains indented code, like so:
<div class="column-container">
<div class="column">text</div>
As of this example, you can see that the container div contains spaces/tabs before the column div is programmed. These spaces/tabs are rendered as characters and so they will obey to whatever the css is telling the characters to do in that container div.
You can use flexbox.
Create a outer div having id as flexdiv which will contain both the div of expiry and CC number.
Then write following code:
#flexdiv
{
display: flex;
justify-content: space-between;
div{
display:inline-block;
box-sizing: border-box;
width:49%;
}
}
Codepen Example
Here is the guide for flexbox: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Pen: http://codepen.io/anon/pen/jqwJMg
Comments: just add font-size:0 to the form.
These are the changes I made:
.minicontainer {
width:50%;
}
form {
font-size:0;
}
When you add two element inline(50%-50%) you should make sure that the font-size is zero
My problem is with the header. So I basically have 3 columns of divs. I want the middle one to have a constant width of 980px, and then I want the left of the header to extend to the end of the browser window with a blue background color. As for the right of the header, I want that to extend to the end of right side of the browser with a black background color. It kind off looks like this:
<------------------------------[blue][center header][black]---------------------------->
I've done my research and all I could find so far are two columns with a fixed left column with the right column filling up the rest of the space. I wonder how this can be applied to my problem?
Would it be like:
<div style="width:100%;">
<div style="display:table-cell; background-color:blue;"></div>
<div style="width: 980px;">my header</div>
<div style="display:table-cell; background-color:black;"></div>
</div>
Thank you!
A simple solution - basicaly using your exact stying, but putting another block in the central table-cell element, something like this span here:
<div class="wrapper">
<div class="left"></div>
<div class="center"><span>my header</span></div>
<div class="right"></div>
</div>
I moved all the inline style to a separate CSS block and used class selectors:
.wrapper {
display:table;
width:100%;
}
.left {
display:table-cell;
width:50%;
background-color:blue;
}
.right {
display:table-cell;
width:50%;
background-color:black;
}
.center {
display:table-cell;
}
.center span {
display:inline-block;
width:900px;
}
here is a jsfiddle
and here I made the center much narrower for a better illustration: jsfiddle
Hope this helps =)
Unfortunately there isn't a super smooth way of doing this that is also has wide cross compatibility support. There is a CSS spec for display called flex or flexbox which would do what you want beautifully and elegantly, but it has very limited support at the moment. Here is some resources on flexbox for your perusal...
http://css-tricks.com/old-flexbox-and-new-flexbox/
In the meantime, you can achieve the layout you want with some basic CSS jiggery-pokery that will get you what you want, but it requires absolute positioning your middle div.
Heres the JSFiddle: http://jsfiddle.net/CW5dW/
Here's the CSS:
.left {
width: 50%;
height: 300px;
float: left;
padding-right: 160px;
box-sizing: border-box;
background: red;
}
.right {
width: 50%;
height: 300px;
float: right;
padding-left: 160px;
box-sizing: border-box;
background: blue;
}
.middle {
position: absolute;
width: 300px;
height: 300px;
left: 50%;
padding: 10px;
margin-left: -150px;
box-sizing: border-box;
background: orange;
}
What is going on here you might ask?
Basically, we are taking the div with class middle and removing it from the flow of the document. This allows us to float our left div left, and our right div right, with widths of 50% in order to fluidly take up ALL space of the browser.
We then tell the middle div to take up 300px of space (in your case 980), and we tell it to go 50% of the total width of your browser from the left. This doesn't center it though, because its calculated from the left edge of your div. So we give it a negative margin space of half it's width, to sort of "move" that left edge to the center of the div.
Then, since we know the middle div has a width of 300px (in your case 980), we can then say that the left div should have some padding on its right edge greater than or equal to half the middle divs width, in my example that's 150px, and I added 10px more so text couldn't come right to the edge of the div, so 160px total. We do the same for the right div but for it's left side. This limits the content of those two divs from falling underneath our middle div.
This answer is not an "answer" as such - it's an extended comment to #Michael's post. I have, however, posted another answer - a jQuery solution.
Regarding #Michael's answer (which is a very tidy solution indeed) there is a tiny issue that if you remove your height declaration (which the OP undoubtedly will) then the backgrounds for the various columns become exposed - this method relies on the backgrounds all levelling out at their bottom edge in order to make the design coherent. If the OP's design doesn't have backgrounds behind the columns then this solution should be fine. If backgrounds are required (which they might be judging by the question wording) then it could be awkward. Two solutions to this...
a simple javascript that scans the page for column length, finds the longest, and matches all shorter ones to the maximum.
The other (and probably better) solution is to drop a background into your with the columns already on it (it only needs to be 1px high I guess) - just make sure the central white band is 980px wide and the side columns extend off a thousand or so pixels to accommodate even the largest of browsers
OK, here's my solution. This will present a "common or garden" three column fixed width layout to all users and then adjust it for users with javascript enabled (which, let's face it, is the vast majority of users). The benefits of this solution are that the layout will behave like any ordinary 3 solumn layout without the quirks you can experience from using more advanced CSS tweaks like absolute positioning and fixed heights.
Fiddle here... http://jsfiddle.net/vuary/
You should be able to see what's going on with the HTML and CSS... it's basic stuff. The jQuery is pretty straight forward too:
$(document).ready(function(){
// find the width of the browser window....
var docuWidth = $(window).width();
// find the width of the central column as set by the CSS...
// (you could hard code this as 980px if desired)
var centerWidth = $('#center').width();
// figure out how many pixels wide each side column should be...
sideColWidth = (docuWidth-centerWidth) / 2;
// then set the width of the side columns...
$('#left,#right').css({
width:sideColWidth+'px'
});
})
EDIT
Converted the jQuery to a function that is called when the document is ready, and again if the viewport is resized... just in case:
http://jsfiddle.net/aKeqf/
I have an issue much like this user, but I want to take it a step further and make my image have a height that responds fluidly to its container.
I made a thing to demonstrate here.
What I want to do is to give the container div class "navcont" (the grey area) a fluid height. If I take out the height, I'm unable to stack similar divs in the same column, not to mention the lovely (but obligatory) overflow:hidden hiding everything.
Very appreciative of any and all help; thanks c:
You need to do some fixes:
.subnav img{
position:relative;top:0;right:0;bottom:0;left:0;
z-index: 1000;
}
.navcont{
margin: 20px;
position:relative;
}
I'm having a very hard time trying to come up with html/css for a layout to suite the following:
Where the left area is a static menu. The right area is dynamic content, generated using a call to ASP.Net's RenderBody method. You may not believe it, but I have been trying to figure this out for hours. I keep getting either the right section ending up underneath the left section taking 100% of the width or not displaying at all, with Chrome's object inspector saying its 0 pixels wide.
I feel like a complete idiot as this seems as if it should be easy as pie. Could I please get some help?
There's several ways to go about this. Here's one not particularly fancy but straight-up way to go about it:
<body>
<div id="menu">MENU</div>
<div id="content"> content <br /> content <br /> content </div>
</body>
CSS:
div { border: 2px solid black; } /* demo purposes */
#menu {
float: left;
width: 150px;
}
#content {
margin-left: 154px; /* menu width + (2 x menu.border-width) */
}
See this jsfiddle for a working sample.
This solution has the added benefit that your content region will take up exactly 100% of the remaining width of its parent:
<div class="parent">
<div class="content">blah...</div>
<div class="left-menu">blah...</div>
</div>
CSS:
.parent { padding-left:200px;width:100%; }
.content { position:relative;float:left;width:100%; }
.left-menu { position:relative;float:left;width:200px;right:200px;margin-left:-100%; }
Excellent tutorial on fluid layouts: http://www.alistapart.com/articles/holygrail
Works in IE7 and newer, Safari/Chrome/Opera/Firefox...
The best way to do this is by using the already considered safe to use box-sizing property.
Take a look at the tinkerbin -> http://tinkerbin.com/AcJjYk0r
It works as you want it to. Fixed width for the menu, percentage based width for the content area.
Then...
...if you want the background-colors to expand to the highest of the heights between the two boxes (remember, one times the menu can be higher than the content box, and vice-versa), then the only way to go about it (no javascript) is to use a background image and place it below the two boxes. With css3 gradients (safe to use too) it's pretty easy. Take a look:
http://tinkerbin.com/3ETH28Oq
In the following HTML, I'd like the frame around the image to be snug -- not to stretch out and take up all the available width in the parent container. I know there are a couple of ways to do this (including horrible things like manually setting its width to a particular number of pixels), but what is the right way?
Edit: One answer suggests I turn off "display:block" -- but this causes the rendering to look malformed in every browser I've tested it in. Is there a way to get a nice-looking rendering with "display:block" off?
Edit: If I add "float: left" to the pictureframe and "clear:both" to the P tag, it looks great. But I don't always want these frames floated to the left. Is there a more direct way to accomplish whatever "float" is doing?
.pictureframe {
display: block;
margin: 5px;
padding: 5px;
border: solid brown 2px;
background-color: #ffeecc;
}
#foo {
border: solid blue 2px;
float: left;
}
img {
display: block;
}
<div id="foo">
<span class="pictureframe">
<img alt=''
src="http://stackoverflow.com/favicon.ico" />
</span>
<p>
Why is the beige rectangle so wide?
</p>
</div>
The right way is to use:
.pictureframe {
display: inline-block;
}
Edit: Floating the element also produces the same effect, this is because floating elements use the same shrink-to-fit algorithm for determining the width.
The beige rectangle is so wide because you have display: block on the span, turning an inline element into a block element. A block element is supposed to take up all available width, an inline element does not. Try removing the display: block from the css.
Adding "float:left" to the span.pictureFrame selector fixes the problem as that's what "float:left" does :) Apart from everything else floating an element to the left will make it occupy only the space required by its contents. Any following block elements (the "p" for example) will float around the "floated" element. If you "clear" the float of the "p" it would follow the normal document flow thus going below span.pictureFrame. In fact you need "clear:left" as the element has been "float:left"-ed.
For a more formal explanation you can check the CSS spec although it is beyond most people's comprehension.
Yes
display:inline-block is your friend.
Also have a look at: display:-moz-inline-block and display:-moz-inline-box.
The only way I've been able to do picture frames reliably across browsers is to set the width dynamically. Here is an example using jQuery:
$(window).load(function(){
$('img').wrap('<div class="pictureFrame"></div>');
$('div.pictureFrame').each(function(i) {
$(this).width($('*:first', this).width());
});
});
This will work even if you don't know the image dimensions ahead of time, because it waits for the images to load (note we're using $(window).load rather than the more common $(document).ready) before adding the picture frame. It's a bit ugly, but it works.
Here is the pictureFrame CSS for this example:
.pictureFrame {
background-color:#FFFFFF;
border:1px solid #CCCCCC;
line-height:0;
padding:5px;
}
I'd love to see a reliable, cross-browser, CSS-only solution to this problem. This solution is something I came up with for a past project after much frustration trying to get it working with only CSS and HTML.