Varying content height and spacing issues using bootstrap grid - css

I have an issue related to using a bootstrap grid in and angular/bootstrap modal. The content that is in the grid are checkboxes with names next to them. The names can vary in length so they can potentially wrap to 2 lines (technically there could be as many wrapped lines as there are unique words in the name, but typically that would be <=2). The oddness that I see is that if there is a name in the first column that has to wrap, but the same row of the 2nd and 3rd columns do not wrap, things look fine and there is no empty line space. Screenshot. When the first column doesn't wrap on a given row but the 2nd or 3rd column does have to wrap, there is a big empty space in the 1st column (2), but when the first column is the one that wraps, columns 2 and 3 work fine (1).
It is especially noticeable when the wrapping cascades, like screenshot 2.
Html for grid:
<div class="row">
<div ng-repeat="courseStudent in course.students">
<div class="col-lg-4 col-md-4 col-sm-4 col-xs-6 cell">
<label>
<div class="input-wrapper">
<input type="checkbox" ng-checked="courseStudent.assigned" ng-click="toggleStudent(course,courseStudent)"/>
</div>
<div>{{courseStudent.student.name}}</div>
<div class="clearfix"></div>
</label>
</div>
</div>
LESS for grid
.row {
.input-wrapper {
float: left;
width: 14%;
}
}
Does anyone know how, if possible, to have the grid collapse that empty space evenly? When I look in the dev tools, that space doesn't even show up. None of the divs for the surrounding cells have padding or seem to occupy that space. Any ideas?
bootstrap 3.3.1
angularjs 1.2.15
angular-bootstrap 0.10.0

The reason this happens is that each of the columns uses float left to create the grid. So, you have a couple of options:
If you know the maximum height your inputs, then you can give your cell class a set height. This might not be ideal since you're dynamically generating your content.
Use a plugin like Masonry to make the content 'fit' into the available space. This creates a cool tiled effect, but may not be ideal for your particular content.
Use jQuery or vanilla Javascript to dynamically adjust the column heights to be equal to the maximum height of the tallest column div.
A jQuery example of the third option would look like (actually, I guess since you're using AngularJS, you should do this in a directive, but here's an example anyway):
var row=$('.row');
$.each(row, function() {
var maxh=0;
$.each($(this).find('div[class^="col-"]'), function() {
if($(this).height() > maxh)
maxh=$(this).height();
});
$.each($(this).find('div[class^="col-"]'), function() {
$(this).height(maxh);
});
});
P.S. There's really no need to include a col class for every breakpoint as you have done here: <div class="col-lg-4 col-md-4 col-sm-4 col-xs-6 cell">. It is sufficient to just write: <div class="col-sm-4 col-xs-6 cell">. Think of col classes as additive. You only need to specify one at a particular breakpoint if you want to change the behavior at that point.

The official Bootstrap answer, in the link in #jme11's comment needs to be a top level answer. See also his link to the bootstrap docs. Insert this div between the rows which need to be reset.
<!-- Add the extra clearfix for only the required viewport -->
<div class="clearfix visible-xs-block"></div>

Related

How can I adjust the number of columns per row with bootstrap

Using Bootstrap v4alpha and I am trying to layout 24 pictures w/ caption underneath in grid. Let's call a tile a picture with its caption.
1) I want the tiles to be aligned vertically and horizontally as we would have if using a < table > tag with align top and left. My pictures are of the same size, but the caption length varies.
2) the number of columns adjusts with screen size. On a small screen, we would have 2 columns and 12 rows. On a medium screen 3 cols by 4 rows. On a large screen 4 cols and 3 rows.
I tried the Cards Columns and it's almost what I need, except the masonry look. I want them also aligned in rows.
I also tried the Grid Options with col-sm-6, col-md-4, and col-lg-3 however the problem lies in the fact I need to wrap a fix number of tiles within a tag < div class="row" >.
This problem also exist in previous versions of Bootstrap, but if there is a specific solution for v4, I would like to know as well.
You can just wrap all .col-*-* with one single <div class="row">...</div>. Your content will wrap when needed.
Now, as for your other question: You don't need to make sure that there are exactly 12 columns in each row for each screen size. If a column doesn't fit anymore (for example you have .col-*-11 and then .col-*-2) it will go to the next row automatically, even if the previous row is not 100% full.
Another example taken from Bootstrap's documentation
<div class="row">
<div class="col-9">.col-9</div>
<div class="col-4">.col-4<br>Since 9 + 4 = 13 > 12, this 4-column-wide div gets wrapped onto a new line as one contiguous unit.</div>
<div class="col-6">.col-6<br>Subsequent columns continue along the new line.</div>
</div>
Here .col-4 would introduce columns 10-13, but since there are only 12 columns, the whole div goes to the next row.
Bootstrap 4
I made a fiddle to show you, how this would work in Bootstrap 4. v4's grid system is based on flexbox and in flexbox an items will grow to use all available vertical space. This means that in a row of columns, each column will be as tall as the tallest column.
This is a huge difference to Bootstrap 3 and means that there is no need to compensate for different heights of the content.
Bootstrap 3
I originally based my answer on Bootstrap 3 and there are a few differences, so I'll keep that original answer (slightly modified) here as well for anybody who needs it.
In Bootstrap 3, you can omit the .row altogether and use .container as the parent to all the .col-*-*.
You can check out this fiddle to see the difference between using .row and not using .row to layout a grid of images. Just adjust the width of the result-frame and scroll down to see the difference when there are 3 images in a row. Of course you can also use one single .row to put all your .cols inside.
Compensating for different content height
However, since Bootstrap 3 uses floats instead of flexbox, this introduces the problem that if your columns are not the same height, the next column might start at the right of the highest element of the previous column when you want it to start at the left of the screen. So in order to push an element below all previous elements, you need to clear these floats.
Bootstrap 3 provides a class for this, you can just insert <div class="clearfix"> whenever you want to clear the floats. Additionally, you will have to hide that div for screensizes where you don't want to clear the floats, you can use the classes .hidden-* to achieve that.
<div class="container">
<div class="col-sm-6 col-md-4 col-lg-3">
</div>
<div class="col-sm-6 col-md-4 col-lg-3">
</div>
<!-- on small devices the first row is full here, so we add a clearfix and hide it for medium and large sizes -->
<div class="clearfix hidden-md hidden-lg"></div>
<div class="col-sm-6 col-md-4 col-lg-3">
</div>
<!-- on medium devices the first row is full here, so we add a clearfix and hide it for small and large sizes -->
<div class="clearfix hidden-sm hidden-lg"></div>
<div class="col-sm-6 col-md-4 col-lg-3">
</div>
</div>
Again, I made a fiddle to show the whole thing in action.

CSS tricky column layout

I have a two column layout, where in first column there is always one item per row and in second column there are any number of items. The problem in my example is that the sizes differ and float only works, if the first column item is higher than the ones in second column.
I know best would be to wrap the items of the right column into one container, but I cannot change the structure of the HTML, I only can do some CSS and/or JavaScript (including JQuery). But I would prefer a CSS only solution.
I also cannot set the height of the first column items statically, because the amount and height of the right column items is dynamic.
The expected result:
See JSFiddle for my current approach:
https://fiddle.jshell.net/uqh9uz5o/
Thanks,
Ingo
You could try wrapping the "other" items in another div with its own float.
<div class="item">
<div class="label">2 label</div>
<div class="wrapother">
<div class="other">2_hallo1</div>
<div class="other">2_hallo2</div>
<div class="other">2_hallo3</div>
</div>
</div>
.wrapother {
float:left;
width: 80%;
}

CSS text wrap vertical alignment

I'm using Bootstrap and I have a row with 6 grid columns. The first column is defined like this:
<div class="hour-item col-sm-1 col-ms-1 col-sm-offset-3 col-ms-offset-3">
<div class="hour-label" id="hour-label-1"></div>
<div class="hour-value" id="hour-value-1"></div>
<div class="hour-weekd" id="hour-weekd-1"></div>
</div>
The rest of the columns are pretty much the same, without the offset classes, and the inner div id numbering increments (-2, ... -6)
My objective here is to have the middle divs (hour-value-x) always aligned between them, a straight line. But the problem is that when text on the first inner div wraps to a second line, it pushes down the other two below it, and that column becomes vertically "misaligned" with the other columns.
This has been answered many times before on this site.
There are several ways this can be done but the best is to use some javascript to match the heights of the different inner divs. Though the js that Wes Duff posted is good it will not cover all situations such as when a user resizes their browser. Using something like match height would be better.
This is an age old issue. :?
Solution I have come up with is to use a JavaScript.
function autoHeight(ele){
var height = 0;
ele.each(function(){
if($(this).height > height){
height = $(this).height;
}
}).each(function() { $(this).height(height); });
Loop through and find the height for each element then assign the tallest height to each element.
<div class="hour-item col-sm-1 col-ms-1 col-sm-offset-3 col-ms-offset-3">
<div class="hour-label" id="hour-label-1"></div>
<div class="hour-value" id="hour-value-1"></div>
<div class="hour-weekd" id="hour-weekd-1"></div>
</div>
//javascript (using jQuery) will look like
autoheight($('.hour_value'));

Twitter-bootstrap: How to use row-fluid class properly?

I have a problem understanding how row-fluid class works. According to the documentation it adjusts itself to fluid design such as responsive design. So if it has enough space it makes it fit on the same row otherwise it goes to the next line.
However looking at this example here : https://duelify.com/
Strangely enough the first three article headers fit on first row.
Second row and rest are slightly pushed to the right. But looking at the html (below) no additional classes are involved to cause this 'side effect'.
Why aren't the article headers fitting in the one row. Why is there this random gap in between? Is there a way to make them appear ordered without any gaps in between?
In your case, proper code will be like
<div class="row-fluid">
<div class="span4"></div>
<div class="span4"></div>
<div class="span4"></div>
</div>
<div class="row-fluid">
<div class="span4"></div>
<div class="span4"></div>
<div class="span4"></div>
</div>
etc...
In every row-fluid class maximum sum of span classes must be up to 12. Span classes have left margin. Only last child in one row-fluid don't have left margin.
Look again now at examples on Twitter Bootstrap documentation. "For a simple two column layout, create a .row and add the appropriate number of .span columns. As this is a 12-column grid, each .span spans a number of those 12 columns, and should always add up to 12 for each row (or the number of columns in the parent)."
There are a couple of things going on here. Remember, by default, the total size of the spans in a fluid-row should add up to 12. There is quite a bit more here, so when the css defines the width of a span4 as approximately 33% they are actually exceeding 100%, so they are going to a new line. But they are not clearing, so you end up with them looping around and making columns like on the page.
The reason you have the space to the left of what would be the second row is that bootstrap defines 'gutters' to give the columns some margin. Because of the excess columns being used you see them. There is specific css to reduce the gutter on the first span of a row to 0, hence why there is no space on the first one.
The subsequent 'rows' have only two columns because the presence of the additional gutter throws off the math and makes the three span4s add up to more than 100% width, causing them to wrap.
The following code will work after container (for Responsive layout):
<div class="container-fluid">
<div class="row-fluid">
<div class="span4"></div>
</div>
<div class="row-fluid">
<div class="span4"></div>
</div>
</div>

Must Bootstrap container elements include row elements?

From my reading of the documentation, it seems that .container is the "parent" wrapper for the .row and the divs that contain the .spanX (where the x totals 12). However, it doesn't seem like there is a .row in their navigation example.
Also, on their documentation site, the .container is wrapped by a couple of navbar related divs.
Can anyone elaborate a bit on how the framework should work? I'm new to it.
The .row class is not required inside a .container, but it is a good idea to include it anyways when you start incase you want multiple rows later on.
All that .row really does is make sure that all of the divs inside of it appear on their own line, separated from the previous and the following .rows.
For the .container inside of the .navbar divs, that is a separate thing that is required to make the navbar line up with the rest of the page. If you look further down in the rendered HTML, you'll see that there is another .container that is not inside any .navbar divs, and that is the one with all of the main content.
A Complete Example
<div class="container">
<div class="row">
<!-- These divs are inline and do NOT fill up the full 12 columns -->
<div class="span4">...</div>
<div class="span4">...</div>
</div>
<!-- This is a automatically a new line of divs -->
<div class="row">
<!-- This div will appear below the previous row, even though it
would fit next to the other divs -->
<div class="span4"></div>
</div>
<!-- These will appear in their own row, but may act
unexpectedly in certain situations -->
<div class="span4"></div>
<div class="span4"></div>
</div>
In Short
.row defines a row of divs, like the name implies. Each one indicates a new line of divs, no matter if the above line is full or not.
The answer is much simpler than those given. No, .container does not have to contain any specific code, and it has no encumbrances on what contains it...
What .container does is serve as a "wrapper" to "contain" the size of any and all elements wrapped inside of it. And .container can wrap pages or components. So, if you want a page similar to those Twitter Bootstrap's docs, with a "fixed" width and equal margin on both sides, then only a single .container is necessary to wrap all of the content on the page.
There are other uses for .container as well; have you noticed how the top navbar in Bootstrap's docs (.navbar-fixed-top) spans the full width of the screen, but the nav items inside the navbar are "contained" to the width of the content? This is because the .navbar-fixed-top is not inside a .container but the .nav inside it is.
The bootstrap grid is composed of 12 columns that can be adjusted in any combination within a row as long as they add up to 12. You can think of them as containment rows such as the likes of table rows, which are meant to separate different rows of content. Within the grid, the .row container has a separate task and is there (and required) to readjust the last grid columns gutter width, which varies depending on screen size (if the responsive sheet is included). If you look at the css behind the .row class you will notice that it has a property of margin-left:-30px by default (once again it can be greater or less depending on screen size), a property which is meant to "remove" the gutter from the last column in the row; without it the grid would not readjust the gutter and it would break onto a second line.
Now, the reason why the .row container is a child of the .container container is because the .row container is only meant to separate "lines" of content, not to contain sections and more over center content in a page. As such, the reason why the navigation example did not have one was probably due to the fact that the nav elements is lacking in gutter width, since it was meant to be a full block element and not a grid, so there was no need to reset that last loose gutter.

Resources