CSS Grid Layout: Three rows grid - html

I'm curious is it possible to use the Grid Layout CSS to create such thing:
************************
* row #1 *
************************
* *
* *
* row #2 *
* *
* *
************************
* row #3 *
************************
So the grid must fill the full body height. And there's also some restrictions for other elements:
The row #1 is aligned to the top of the grid and can change it's
height (but has a max-height value)
The row #3 is aligned to the
bottom and can change it's height (also has a max-height value)
So the row #2 must fill all remaining space in grid.
The grid container should not overflow the html body.
There's an example what I achieved: 3 row grid layout.
I also can make everything with absolute position like this but there's no use because I can automatically calculate the row #2 margins without any imperative js code.

I see that the original question is marked as answered, but as the original included an attempt to use the CSS Grid Layout module to solve the problem, I thought I'd complement the answers with some solutions using newer standards.
Using flexbox
First of all, this kind of layout is pretty easy using flexbox. The flex-grow property allows you to define elements that fill the remaining space in this very way. JSBin example using flexbox here
Note: Not using all prefixes (e.g. to target IE10 etc) in the quick demo, but if you use something like autoprefixer it's kind of trivial. Also, beware of bugs relating to things like vh units in iOS and min-height flexbox columns in IE.
Using grid layout
Note: This demo will only work in Chrome Canary at the time the answer was written!
Grid layout is picking up pace and the spec has stabilized a bit. Chrome Canary has an implementation that is pretty far along, as does the WebKit nightly builds.
Grid layout has the same type of flexible sizing as flexbox, and moves the layout mechanism to the container element instead. JSBin demo – remember, Chrome Canary only at the time of writing. (It would work in WebKit nightlies as well with the right prefixes.)
Basically, the whole thing boils down to these lines:
body {
margin: 0;
display: grid;
grid-template-rows: auto 1fr auto;
grid-template-columns: 100%;
height: 100vh;
}
The above means "Use the body element as a grid container, place items in it in source order, in a single column that is 100% wide, and size the first and third row according to content, and the middle one takes up all the space that is left". We don't need to specifically place the items inside the grid: they will auto-place themselves – we could change order etc if we wanted though. Grid Layout can do many more advanced things!
Most browser vendors are working on finishing their first grid implementations, so it's fun & worthwhile to start playing with it. :-)
Until then, the flexbox version gets you pretty good browser support.

You can do this with display:table property See Spec and Compatibility
Working Demo
CSS
#container {
display:table;
}
#head, #content, #foot {
display:table-row;
}
Edit:
Updated Fiddle
Added div inside table-row to prevent overflow

what about setting percentages heights like this:
.head{
height:10%;
max-height: /*max height allowed*/;
}
.content{
height:80%;
max-height: /*max height allowed*/;
}
.foot{
height:10%;
max-height: /*max height allowed*/;
}

Related

flexbox min-width failing in IE and Edge

I have some table that set width for elements so some columns will have at least some percent of a width of the container.
I want to use flexbox to center this table and set the minimum-width for it.
The goal is to have centered table with some minimum width for which some columns will have the same width (same ratio).
If some cells have longer texts then I don't care if ratio will broke (width of this column will be bigger then other). I just care that it has nice and same width of columns for common case (small amount of text data in cells)
I was able to came up with solution that works on Firefox and Chrome (link).
But for Edge and IE11 the table stretch as if it was not in flex container (try to comment display: flex; on Firefox or Chrome and the result is stretched table like on Edge.
Also it looks that sometime setting columns work (link2). But I don't see the pattern of when it break in Edge/IE11.
Here is more production example that I want to achieve (works in Chrome/Firefox, stretch in Edge/IE11): "production" table example.
Any ideas how to achieve what I want on Edge/IE11? (I put in bold what I want to achieve).
It would be good if I could keep using flexbox container (it might require more changes in my codebase) but I think I will be fine with deleting style=width:p% from <col> if that's necessary.
The min-width rule is apparently being ignored in Edge / IE11.
There's an equivalent command that seems to work.
Instead of:
.inner {
min-width: 800px
}
Use:
.inner {
flex-basis: 800px; /* 1 */
flex-shrink: 0; /* 2 */
}
revised codepen
notes:
flex-basis is a substitute for width, in this case (see: flex-basis vs width)
flex-shrink: 0 ensures flex-basis / width cannot decrease below 800px (hence, both rules together emulate min-width)

CSS grid-template responsiveness

So I'm testing CSS's grid abilities and one of the things I can't figure out is zooming levels from browsers and the behavior of images within them.
e.g. If I change the viewport it's all fine. The grid and it's images scales perfectly but there are users who use ctrl+- or cmd+-.
If this is used the image is scaled like it should but the grid doesn't scale like I thought it would.
I created a basic grid containing 4 columns and no rows. I don't want to have the width full screen so I added a margin on the container holding the grid of 25%.
The grid is place within the center. Here is a Fiddle.
https://jsfiddle.net/kagprzae/
Can anyone see where I missed a turn?
---- SEMI-SOLVED IT----
So The trick is to use absolute pixels. That way you can use ctrl/cmd+-
The downside is that the grid isn't responsive anymore so you have to use #media queries to change layout...
I'm not sure what I believe would be the best approach to do this.
---- COMPLETE SOLUTION NO JS ----
So after some (a lot) of testing and thinking I came up with the following solution.
Give the .container a width (in my case I could) and calculate your grid according to a 100% width.
You can margin:0 auto; to center the div.
See this fiddle

CSS table, varying dimensions

I'm working on a responsive layout that displays some <div> boxes as part of a rectangular grid:
http://sl.cosd.com
The six boxes you can see on this page are all ungrouped in the HTML source, all in a row:
<div class="control">
<div class="controlContent">
<a>SOME VARIABLE-HEIGHT CONTENT including an image which might float</a>
</div>
</div>
The control divs assign the boxes percentage widths to first the whole, then 1/2 or 1/3 the screen width, so they double & triple up into rows as the screen size is increased. The controlContent divs assign properties like padding, margin, background, border-radius, etc.
I have imagined this as a linear set of boxes, standards-compliant and screenreader-friendly, to be displayed via CSS like a table. I know CSS2.1 allows elements to be assigned properties like:
display: table;
display: table-row;
display: table-cell;
My main problem: I have assigned display: table-cell to these elements (via the controlContent div) which prevents margin collapse inside the content but does not provide a uniform height to the cell-like divs. I need a way for all siblings on the same row to have matching height.
The smaller cells generally have gaps below them where the gradient background only covers the box height of the cell. (Worse, the text after this array of cells sometimes fills into these gaps: another problem that could be fixed with presentation markup, though one which will probably go away when the first problem is fixed.)
I think I understand the basics of the problem: each <div> which I have told to behave like a table cell has nothing to match its height to, since I have no way of grouping elements into a containing <div> to which I can assign the display: table-row property, since this grouping changes according to CSS media queries.
In my reading about the problem I've heard of anonymous table boxes and anonymous table rows being created but don't know how to use them in this case. Since I'm using the CSS :nth-child() selectors to clear the floating boxes at the beginning of each new row, I'd hoped I could also use these selectors to establish a new table row at every such point... but how?
I'm not married to any particular solution. I'd just like to know the best-practice way of doing this. I'm hoping to find a solution that doesn't involve presentation markup, especially since a general solution should provide a responsive variable-dimension table for any number of cells, not just a small, easily factorable number like 6.
display:table-cell; should give the div/columns the same height, as long as the parent div has display:table; set.
Check this fiddle (you can add/remove as many cols as you want).
Another solution is to give .control a fixed height, then you can use height:100%; on controlContent.
If you need to use percentages only, then you've to declare an height on all the parent containers of .controlContent, up to html and body:
html, body, .control, .controlContent {
height:100%;
}
Obviously it's just a simplification. This is the most reliable method, because table-cell is not rendered properly by some older browsers.
On the other hand, you always have to know the height (in pixels or percentage) of all containers.
Then, there's the faux column method, but i don't thinks it suits your case.
Lastly, there's the JavaScript / jQuery method, which in your case would be something like
$(document).ready(function(){
var higherContent = 0;
$('.controlContent').each(function() {
var currentHeight = $(this).height();
if( currentHeight > higherContent ) higherContent = currentHeight;
}).height(higherContent);
});
Which basically (when the page loads) passes through all the controlContent and sets the value of the highest one in the variable higherContent. Then this value is assigned to all controlContent.
Probably not the best jQuery function ever written anyway :-) and you'ld have to adapt it for every resolution targeted by your media-queries.
If i were you, i would probably go for the table-cell method, so that you can set different widths for different resolution, and the layout will adapt in most of modern desktop/mobile browsers. But be sure to test it on as many devices as possible!
EDIT: I see you're using min-width media queries. You can change your code this way:
div.controlContent {
/* other stuff */
display: block;
/* other stuff */
}
#media only screen and (min-width: 480px) {
/* other stuff */
div.controlContent {
display: table-cell;
}
/* other stuff */
}

YUI Grid CSS for 100% width page with custom template width

I am using Yahoo's UI Grids to structure most of my pages. One of my pages is a Google map and I need about a 400 pixel fixed left column to put map legend information into. YUI Grids however only offers 3 columns for their 100% page layouts, namely 160px, 180px and 300px.
Is there a way that I can customize their 'template 3' which provides the 300px column to get my 400px column I need?
I've determined how to do this. Kudos for Nate in the YUI forums for pointing me in the right direction.
To set a fixed left column, you need to divide the column pixel width by 13 to determine the em's for all non-IE browser's. For IE, divide the column width by 13.3333
e.g. wanting a fixed 480px width, 480/13 gives me 36.9231em for non-IE and 480/13.33 is exactly 36em for IE
Using template 3, the CSS is:
.yui-t3 .yui-b {
float: left;
width: 12.3207em; *width: 12.0106em;
}
.yui-t3 #yui-main .yui-b {
margin-left: 36.9231em; *margin-left: 36em;
}
Also, if you want to tweak margin's e.g. zero margin, you can do something like:
#doc3 {
margin: auto 0;
}
Grids is presently deprecated in YUI 3 - a bit of a shock when I saw that. There will be some browser(s) that drop off the A category in July and as a result, Grids will be reworked given that some of the initial design decisions were based on older browsers of course.
There is definitely a way. I think its just a matter of tweaking the CSS to either add in another 400px column, or modifying an existing column to fit your needs. If you are adding another column, be sure to account for the additional width (plus margin) and either reduce width on other elements, or increase the width of your containing element.
If the layout is using 100% width of the browser, width may not be an issue, but if your content is wrapped in a container element which holds all of your columns, be sure to adjust the existing elements to make up for the size of your new column.
EDIT: Also if you are dealing with 100% width layouts, its probably better to size your columns using percentage, instead of a fixed pixel size. Since the containing element for your columns will be the user's screen, if you use percentage then the column sizes should adjust relative to their resolution/window size.
If you want your new column to appear on the left of the your other columns, typically you would place it before the other columns in your markup, and apply a "float:left" property. But, take a look at how the other columns are set up in the YUI CSS, and follow their method.
I hope that helps.
Acorn

How do I specify in HTML or CSS the absolute minimum width of a table cell

Summary
What's the best way to ensure a table cell cannot be less than a certain minimum width.
Example
I want to ensure that all cells in a table are at least 100px wide regards of the width of the tables container. If there is more available space the table cells should fill that space.
Browser compatibility
I possible I would like to find a solution that works in
IE 6-8
FF 2-3
Safari
In order of preference.
This CSS should suffice:
td { min-width: 100px; }
However, it's not always obeyed correctly (the min-width attribute) by all browsers (for example, IE6 dislikes it a great deal).
Edit: As for an IE6 (and before) solution, there isn't one that works reliably under all circumstances, as far as I know. Using the nowrap HTML attribute doesn't really achieve the desired result, as that just prevents line-breaks in the cell, rather than specifying a minimum width.
However, if nowrap is used in conjunction with a regular cell width property (such as using width: 100px), the 100px will act like a minimum width and the cell will still expand with the text (due to the nowrap). This is a less-than-ideal solution, which cannot be fully applied using CSS and, as such, would be tedious to implement if you have many tables you wish to apply this to. (Of course, this entire alternative solution falls down if you want to have dynamic line-breaks in your cells, anyway).
Another hack is the old 1x1 transparent pixel trick. Insert an 1x1 transparent gif image and set its width in the image tag to the width you want. This will force the cell to be at least as wide as the image.
I know this is an old question but i thought I'd share something that wasn't mentioned (Although pretty simple in concept..) you can just put a <div> inside the table (in one of the <td>'s or something) and set the <div> to min-width. the table will stop at the <div>'s width. Just thought I'd throw that out there in case somebody comes across this on google. Also, I'm not so sure about how min-width is handled in I.E6. but that has already been covered in another answer.
I had some success with:
min-width: 193px;
width:auto !important;
_width: 193px; /* IE6 hack */
Based on a combination of Vatos' response and a min-height article here: http://www.dustindiaz.com/min-height-fast-hack/
what about this css property
min-width: 100px
but it doesn't really work in IE6 if not mistaken
if you don't want to do it in the css way, I suppose you can add this attribute
nowrap="nowrap"
in your table data tag
This is a cross-browser way for setting minimum width and/or mimimum height:
{
width (or height): auto !important;
width (or height): 200px;
min-width (or min-height): 200px;
}
IE 6 doesn't understand !important
IE 6 sees width/height:200px (overwriting auto)
Other browsers understand the min- and the !important
I am not 100% familiar with the behaviour of widths in TD elements, but this all works nicely on eg DIV tags
BTW:
Based on a combination of Vatos' response and a min-height article here: http://www.dustindiaz.com/min-height-fast-hack/
This is not working because of the order of the first 2 lines, they need to be in the right order (think about the above) ;)
IE6 handles width as min-width:
td {
min-width: 100px;
_width: 100px;/* IE6 hack */
}
If you want IE6 to handle width like normal browsers, give it an overflow:visible; (not the case here)