Elements in CSS Grid Column, top margin behaves as position top - html

Difficult to come up with a good title - by all means, change if you can.
Traditionally, a margin on an element can be used to move elements around a page relative to its previous elements. So, if I had a div as a column on my page I could shift elements vertically within that by setting their top-margin CSS property.
This is handy in dynamic pages where some elements might not exist according to given condition, eg, a very simple example here:
https://jsfiddle.net/jhartnoll/4s6pcLu0/1/
I have simply defined a column with a div element, positioned two other div elements and made one of them have a 2em vertical gap between it and its predecessor.
If you remove (or set Display:none) element #one then element #two is shifted up the column and positioned 2em from the top of the column, rather than 2em from element #one which is no longer there.
However, if I try to do a similar thing using a CSS grid, thus making the DOM tree simpler and more flexible, I run into a problem:
https://jsfiddle.net/jhartnoll/xvhycg0k/11/
In this case, the columns are set by the CSS grid so are sort of pseudo columns, but when I set my elements to have margin-top: 2em the margin is calculated from the top of the grid column, not relative to a predecessor element.
Therefore, if element #one is not present, #two simply remains 2em down from the top leaving a gap above...
This behaviour renders margin-top useless, because it is exactly interchangeable with top on relative positioned elements.
Is this a bug with CSS Grid, or am I using it wrong, or is there a way around this?
CSS Grid seems great, but I have run into several problems like this where dynamic content is concerned, if elements have potentially variable heights, or may not be there at all, the Grid leaves other elements floating in space, unable to shift up.
EDIT for clarity of the dynamic problem
Thanks for the comments so far. The problem is not with using the layout, I understand how to set up grids, and rows, define sizes, spaces, span etc, the problem is with dynamic content.
Supposing I have an extremely simple product page:
https://jsfiddle.net/jhartnoll/xvhycg0k/42/
Irrespective of the grid spacing, row/column size etc, the concept is simply that I have thrown in a "Price reduced by 10%" splash element above the product title.
Naturally, product pages would be using templates and therefore the HTML and CSS should be fixed and flexible enough to enable elements to be missing or present.
Not all product pages will display the 10% off deal, so on those pages, I would want the Product Title to shift up into the top element position.
This, as far as I can tell, cannot be achieved with grids.
Similarly, if there was a div which contained a product description and underneath it some product cross promotion or something, the description might be of variable length, so with the div as a column example in the my original question, the content would automatically expand the description grid and shift the cross promotion stuff down the page. Again, this can't be achieved with grids?
So, I was messing around with using a grid defining columns only and simply one row per page so that content could be stacked in columns similarly to the original div as a column example, but then I ran into this margin-top problem which, within a Grid is that margin-top is relative to the grid top, not to the elements above.
So I can't find a way of creating a dynamic website, using a template design which allows for conditional elements and variable element dimensions using Grid and without using Javascript to manipulate on page load.
In my mind, there should be an option for a row-shift property to allow elements to jump down a row if the content is too large, or jump up if there is nothing obstructing it... or something like that anyway!

Hey try the following code I guess it will help your requirement!
#column{display:grid;grid-row-gap: 10px;width:4em;height:auto;border:1px solid grey;}
#one{background:red;width:2em ; height:2em}
#two{background:blue;width:2em ; height:2em}
<div>
<div id="column">
<div id="one">
</div>
<div id="two">
</div>
</div>
</div>

Related

Div elements of different width, stack subsequent divs on shorter column

I want to organize data in two columns of equal width, but they may be different heights per element. It's difficult to explain, but if you have div1 of height 500 and div2 of height 400, then add div3 of any height, it should appear directly below div2 rather than div1 because div2 is shorter. However, if div1 was shorter, div3 would instead appear below it.
Originally I was using tables since it's mostly tabular data, but when one of the two text fields are longer than the either (one in left vs. one in right), it stretches the shorter to match the height. I end up with rows of different height, and the element in the shorter column will stretch to fit that row (which is determined by the taller of either element). I don't want it to stretch, I'd rather it stack to minimize blank space.
Here's a mockup of what I'm trying to achieve. At the top you'll see the page with only one element, then below that you'll see with two elements, then below that with three and four elements. The third element goes below the second element because the overall height of the right column is shorter, but the fourth element goes below the first element because after the third is added, the left column is now shorter.
The only site I can think of off the top of my head that uses a similar organization style is Pinterest.
This concept on the web is usually refered to as Masonry.
Here is a link to a javascript library that can help you implement it.
http://masonry.desandro.com/
This can also be accomplished using FlexBox css for modern Browsers.
That has been addressed in this question: using flexbox to get pinterest or jQuery masonry layout

overflow content across elements

I have two DIV elements side-by-side, to create two columns. The two elements both have a fixed height of ~200px (calculated based on window height). I would like the content to overflow from the left DIV into the right, ONLY when the first DIV is full.
Unfortunately, I can't use CSS columns, since it automatically balances content across the columns, instead of filling the first column completely before overflowing.
So far the only option I've found (including here on SO) involves JS, and since the content may include HTML (including block elements), the use of JS is just about my least desirable approach.
Thanks in advance :)
You want something called CSS regions and it is only a working draft atm.
"The CSS Regions module allows content from one or more elements to flow through one or more boxes called CSS Regions..."
Until then, I'd go with a polyfill.

How height is calculated without setting it

I'm trying to get more efficient with building responsive websites and since I'm using Bootstrap (not particularly important for this case - I believe), I was looking into Bootsnipp. I decided to view the site's source and noticed one thing I've never seen before: they did not set a height for any of their containers except for the whole page wrapper and the footer. This baffles me because everything falls into place with the website and it's super repsonsive. I understand the elements where they use Bootstrap's classes like "col-sm-4" and whatnot but does anyone understand the art of making the header, a content container, etc calculate heights without specifying in css? Can anyone explain this concept? I tried Googling but not sure of the correct keywords to find answers.
Also, if you need to see yourself, here is the link to their CSS.
Thanks
Understanding the Box Model is important. As an (overly simplified) rule of thumb, you can think of it like this; there are 2 primary types of elements: inline (span, b, strong, ...) and block (div, p, ...).
Block tags by default are width: 100%. That is to say they will naturally stretch to fill their horizontal area.
Inline tags you can think of as being constricting. They shrik to fit the size of their inner elements. This makes sense when you think of a bold tag: it is not unlike highlighting the text you want to be bold. It stays small to fit the content.
In both cases, though, unless you specify a height, both block and inline tags will shrink their height to fit their inner elements. Because of this, you can think of a website as being a bunch of elements stacked on top of each other, where the top of the page is the bottom of the "stack".
Here is an example of divs without specified heights having their heights changed by the size of the interior content. http://jsfiddle.net/S3q2C/ Notice all the divs have a border to easily see its relative size.
If you don't set an explicit height, containers will automatically grow to fit the content (respectively). Sometimes this is desirable, other times not (think overflow hidden). A possible reason why people use explicit heights in containers could be because of absolute positioning, or if they want to align a nested element that is 50px tall, with another that is 200px tall. An explicit height could also be used to maintain perspective say for a picture or other element (maybe a series of elements). While this answer is the end all be all you might be looking for, the key thing I'm trying to pass along is that an explicit height is used when needed, not all the time.
Here's a quick demo showing you two <div> containers, one with a height set, and another with no height.
http://jsfiddle.net/xrZ73/1/

CSS & Nested Divs - Parent Div Won't Take Child Height, Overflow:auto not a good fix

The Context:
I'm building out a div roster to use with jQuery or PhP for my roleplaying Star Trek Fleet (nerdy, yes, I know). I need my divs to behave in certain ways to make it robust enough to pull from XML and generate the roster automatically and auto-size my divs to fit however many names are added.
It will help to take a look at my current build example with Firebug/the like to understand what I'm doing.
Requirements:
Each subsection (Outpost Personnel, Outpost Defense), needs to have a number of divs:
1) The background image & subsection container (div id= outpostPersonnel in this example)
2) Sub-sub section container for each side of the listing, left and right. (Think newspaper paragraph.)
3) The top n number of roster names needed to fill/align to that background image in requirement 1. (div id= initialCommandTags (left side listing) and initialPersonnelTags (right side listing))
4) Div that stretches with n number of additional roster names. (div id = overflowCommandTags, overflowPersonnelTags, )
5) A colour div stripe to make it look like LCARS is still encapsulating the n number of roster names from requirement 4. (div id = colorStretchLeft)
The Problem:
I cannot get the parent subsection- the div from 1 (outpostPersonnel) to adhere exactly to the height of ALL its child divs- all the way down to the height of the overflowCommandTags/overflowPersonnelTags div.
One way I've tried it, and the next subsection (Outpost Defense) overlaps the overflowCommandTags div. The other- which is the way I have my example now (and where I gave up)- puts a ~160 pixel high blank space between the end of the overflowTags div and the top of the next subsection (outpostDefense).
If you firebug my current build example, you'll see that the parent div (outpostPersonnel) extends way the heck down, even though none of its child divs are that tall.
Overflow:auto and Overflow:hidden are NOT viable solutions insofar as I have read, since I need the divs to expand fully, and WITHOUT a scrollbar.
I'm completely stumped. Watch it be a really simple solution, too. Is it something to do with the fact that the parent div is only a BG, while the child divs have actual content?
Thank you for bearing with me this far!
Cheers!
((Also the reason why my div style stuff is in-line is because I'm embedding this on an Enjin page and I can't call a *.css file.))
There are a few things to mention here but I'll start with the reason for the gap in between the two sections.
From what I can see from your inline styles you have used position: relative and varying top andleft values to achieve the desired layout. On the element with ID personnelContainer you have added top: -230px. This is what is causing the gap.
When you position an element relatively you have to imagine that the element is in its original position and that you've just visually moved it. In other words, moving the element does not change the flow of the page, so applying the negative top value as in your example will not change the height of the container. (good reference: http://reference.sitepoint.com/css/relativepositioning)
With this in mind, you could go the route of applying minus top values to each of the sections that follow in order to close the gap, however you are likely to find that this complicates matters further and leads to overlapping content.
The best advice I can give is to read the following articles on floated layouts:
http://css-tricks.com/all-about-floats/
http://www.quirksmode.org/css/clearing.html
Relative positioning has its applications but in this case you should use the float property to achieve your layout. If you read the articles above it will give you a good grounding in floated layouts and how to ensure your sections contain everything correctly. As long as you don't set any fixed heights on any of the child elements you will find they expand to accommodate any amount of content.

Inline divs won't listen to authority

I need a little bit of help disciplining my HTML. It seems to be acting up.
Anyway, the content area of a page I'm working on has two columns. To get the multi-column look, I'm not using one containing div for each column because some of the "rows" in the column need to be lined up.
So instead, I'm basically using several "rows" with two inline divs per row -- one for left content, one for right. Most of them are working correctly..but for some reason, my last row isn't. No matter what, it will not listen to me when I give it a width.
Here's what the relevent HTML looks like:
<div id="mainContainer">
<div id="topBar"></div> //full width
<div id="featured"> //this "row" is working fine
<div id="featuredVideos"></div> //these two
<div id="featuredLiterature"></div> //are inline
</div>
<div id="browseButtons"> //this is the "row" that is acting up
<div id="litBrowse"></div> //these two
<div id="vidBrowse"></div> //are inline
</div>
</div>
In the mean time, what types of situations can cause a div to not listen to a width? I even went so far as to give every single child div inside litbrowse and vidbrowse1 the same width that they have, 450px, and no dice. All of the content above it, which has essentially the exact same structure, is working fine. The only difference, maybe, is that the "row" above the row in question is comprised of two floating divs.
Here is a jsfiddle showing the issue. The bottom two divs (Browse lit by category, browse vids by category) should be spaced out, but they're scrunching together because they won't take their 450px width.
The problem is that you are saying that .browseBtn is inline. Inline elements don't take widths, only block level elements do.
Using inline-block instead will do what you want. It is inline enough to make the divs side by side and block enough to allow you to specify the width.
See http://jsfiddle.net/abtFr/2/
SECOND EDIT - Others have responded saying to use display: inline-block instead of display: inline. inline-block is not compatible with IE7. HOWEVER, we can make it compatible by appending
zoom:1;
*display: inline;
to the element using inline-block. To make compatible with IE6, you need to specify a height, so add
_height: [yourheight]px;
The underscore will target IE6 only.
Alternatively you can float the elements left, in which case my original reply may be relevant.
EDIT - I responded without seeing the jsFiddle; this response can probably be largely ignored.
To answer your question, floating an element will cause it to be taken out of the normal layout. If a div is floated left inside another div, it will be placed to the far left of that container, but its dimensions will not be taken into account when sizing that container div; in other words, that container will act like there are no divs inside.
To fix this you need to place another (empty) div inside the container, after the floating divs, and assign the style "clear: both" to it so that it will take the floating divs into account when being positioned. In turn, the container div will see the last cleared div and resize to take it into account.
Alternatively, sometimes you can skip adding the cleared div inside the container, and just add the style "overflow: hidden" to the container itself. This is somewhat of a hack, but a pretty robust one as far as hacks go.
Hope this solves your problem; if not we'll have to wait for more information.
It's simple, yes, you have a div, but you define its display as inline (with .browseBtn definition). So it's not a block-element anymore and it doesn't listen to width definition.
I've corrected the fiddle, although it might have other side effect.