Equalizing horizontal column paddings at unknown number of columns - css

I am struggling solving a problem with a multi-column setup.
Given a simple setup of three columns I want to adjust the padding so that each gap between the columns is of the same size (2rem). But, the tricky part: I want to be able to use the same rules for 2, 3, 4 or even 5 columns.
I am using PureCSS to create the multi-column setup itself. Knowledge of this framework should not be necessary though, as my problems don't have to do with it.
At the moment there is the following markup:
<div class="pure-g">
<div class="pure-u-1-3"><div class="myblock">content col 1</div></div>
<div class="pure-u-1-3"><div class="myblock">content col 2</div></div>
<div class="pure-u-1-3"><div class="myblock">content col 3</div></div>
</div>
Each column is of 33.333 % width, of course. To create the gap in between, my idea is to use an inner wrapper for each column, that pushes it's content away from the sides.
<div class="pure-g">
<div class="pure-u-1-3 col">
<div class="col-wrapper">
<div class="myblock">content col 1</div>
</div>
</div>
<div class="pure-u-1-3 col">
<div class="col-wrapper">
<div class="myblock">content col 2</div>
</div>
</div>
<div class="pure-u-1-3 col">
<div class="col-wrapper">
<div class="myblock">content col 3</div>
</div>
</div>
</div>
Now I give the .col-wrapper some padding. But here's where I can't figure out a clean solution that works for all column counts. My idea is:
.col > .col-wrapper {
padding-left: 1rem;
padding-right: 1rem;
}
/* Overwrite padding for an exact left alignment */
.col:first-child > .col-wrapper {
padding-left: 0;
}
/* Overwrite padding for an exact right alignment */
.col:first-child > .col-wrapper {
padding-right: 0;
}
But given this CSS, the first and the last columns are always of different size than the rest, as they have 1rem less padding.
Next idea was, to adjust it a bit further and this is nearly perfect, but it causes the first/last and other gaps to differ.
.col > .col-wrapper {
padding-left: .67rem;
padding-right: .67rem;
}
/* Overwrite padding for an exact left alignment */
.col:first-child > .col-wrapper {
padding-right: 1.32rem;
padding-left: 0;
}
/* Overwrite padding for an exact right alignment */
.col:first-child > .col-wrapper {
padding-right: 0;
padding-left: 1.32rem;
}
And here I am stuck. How would you adjust it to create even gaps?
Thanks for your help :-)

I am using PureCSS to create the multi-column setup itself. Knowledge
of this framework should not be necessary though, as my problems don't
have to do with it.
Your problem is related to the use of purecss in that you are constraining yourself to finding a solution starting from columns set at fixed percentages.
You could easily achieve equal width columns without using purecss and use flexbox instead (see example http://codepen.io/imohkay/pen/gpard).
<div class="equalHMWrap eqWrap">
<div class="equalHM eq">boo <br> boo</div>
<div class="equalHM eq">shoo</div>
<div class="equalHM eq">clue</div>
</div>
css
.eqWrap {
display: flex;
}
.equalHMWrap {
justify-content: space-between;
}
.equalHM {
width: 32%;
}
I am not sure if there is a solution possible using the same rules for different number of columns while keeping with purecss. The percentage of padding for left, right, first-child and last-child would always be changing depending on the number of columns in use. But you could calculate it for each scenario and add css rules as applicable.

Related

Is it possible with CSS only, without hardcoded numbers, to have the same computed value as another element?

Good day, I believe that this is not possible, but asking to be shure. I do not know how to DuckDuckGo similar questions, and I have an example:
.wrapper {
border: 1px solid red;
margin: 10px;
}
<div class='wrapper'>
<div>xxx</div>
<div>xxx</div>
<div>xxx</div>
</div>
<div class='wrapper'>
With CSS only: how to have this element the same height, without hardcode?
</div>
Maybe I can wrap this to table (or display as a table) where the height of one row with, say, 5 children will be the same as height of another row with 9 children? I need this for table data representation where I can have empty rows - I need to have them the same height as another rows with data. Looks like now I will need to use Javascript to get computed height :(
CSS grid can do it:
.wrapper {
border: 1px solid red;
margin: 5px;
}
.container {
display:grid;
grid-auto-rows:1fr; /* The magic property */
}
<div class="container">
<div class='wrapper'>
<div>xxx</div>
<div>xxx</div>
<div>xxx</div>
</div>
<div class='wrapper'>
With CSS only: how to have this element the same height, without hardcode?
</div>
</div>

Why are my bulma columns wrapping, despite not having is-multiline set?

I'm using Bulma for column management, and it has a is-multiline class that can be used to allow columns to wrap. However, I'm not using this class, but my columns are still wrapping.
Expected Behavior:
Two columns are always side-by-side, on the same row
Actual behavior:
At certain viewport widths, the second column goes below the first column instead of beside.
Question
If you're familiar with Bulma, would you mind taking a look at this simple example and letting me know if I'm doing something obviously wrong? Thanks so much!
HTML
<div class="body">
<div class="columns">
<div class="column row-name is-narrow">
Row 1
</div>
<div class="column row-cells">
Some data
</div>
</div>
</div>
CSS
.body {
width: 600px;
background-color: #000;
margin: 0 auto 0;
}
.row-name {
background-color: #ffff0088;
width: 50px;
}
.row-cells {
background-color: #ff000088;
}
A JSFiddle: https://jsfiddle.net/8ggyagxp/10/
It turns out if Bulma detects that your viewport is mobile sized, it will stack columns unless the is-mobile class exists on the columns. See here for more information.

Make Bootstrap 3 columns have equal height, visible gutters, and background color

I want to make my Bootstrap 3 columns to be:
of the same height (edit: equal to the highest column, which could change)
have visible gutters separating them
have a background color that matches their equal height
So far I was able to either make them of equal height (with no visible gutter) or give them a gutter and a background. I've been fiddling with this for the past 2 hours to no avail. Naturally, I've read through everything I could find but couldn't solve this riddle. Would highly appreciate your help!
Here is code and codepen with my problem.
HTML
<div class="container">
<div class="flex-row row">
<div class="col-sm-5">
<div class="inner">
<p>Some text and probably an image over here. Not as much as on the other side, but still..</p>
</div>
</div>
<div class="col-sm-7">
<div class="inner">
<p>More content on this side. How can I make the two columns have the same height and have a gutter in between?</p>
<img src="...">
</div>
</div>
</div>
</div>
CSS
div[class^='col-sm-'],
div[class*=' col-sm-'] {
background-color: green;
}
#media only screen and (min-width : 768px) {
.flex-row.row {
display: flex;
flex-wrap: wrap;
}
.flex-row.row > [class*='col-'] {
display: flex;
flex-direction: column;
}
.flex-row.row:after,
.flex-row.row:before {
display: flex;
}
}
http://codepen.io/anon/pen/QEozAj
I don't want columns to be of fixed height because contents will change.
And ideally I would like to have as little extra divs as possible. :)
Edit: Column heights now look okay, thanks to a helpful reply. Still need the visible gutter.

Flexbox grid: cells won't grow

I'm trying to create a grid layout based on flexbox:
.container {
width: 360px; /* Try to change this. Possible values: 240px, 360px, 480px.*/
background: #eee;
display: flex;
flex-flow: row wrap;
margin: 0 -10px;
}
.cell {
box-sizing: border-box;
padding: 10px;
flex: 0 0 120px;
max-width: 120px;
}
.cell.wide {
flex: 1 0 120px;
max-width: 240px;
}
.inner {
background: red;
height: 100px;
color: #fff;
padding: 10px;
box-sizing: border-box;
}
.wide .inner {
background: blue;
}
<div class="container">
<div class="cell">
<div class="inner">1</div>
</div>
<div class="cell wide">
<div class="inner">2</div>
</div>
<div class="cell">
<div class="inner">3</div>
</div>
<div class="cell">
<div class="inner">4</div>
</div>
<div class="cell wide">
<div class="inner">5</div>
</div>
<div class="cell">
<div class="inner">6</div>
</div>
<div class="cell wide">
<div class="inner">7</div>
</div>
<div class="cell">
<div class="inner">8</div>
</div>
<div class="cell">
<div class="inner">9</div>
</div>
<div class="cell">
<div class="inner">10</div>
</div>
<div class="cell">
<div class="inner">11</div>
</div>
<div class="cell wide">
<div class="inner">12</div>
</div>
<div class="cell">
<div class="inner">13</div>
</div>
</div>
This JSFiddle helps to illustrate my problem.
A container element .container can contain any number of cells.cell. There are two types of cells: a regular one with a fixed width (the red ones in the jsfiddle) and a wide one .cell.wide (the blue ones) which are twice as wide but could shrink to the width of the regular cell if there is not enough space in the current row. Each row must be filled completely.
So in the example (see fiddle):
Cell #2 should be wide and push #3 to the next row.
In the second row, which then contains #3, #4 and #5, cell #5 should stay small, because there's no space for a larger cell and rows should be filled completely.
etc
By the way: The grid container is of variable width and rows can therefore contain between two and four cells. You can try this out in the fiddle by changing to width to the specified possible values.
After trying around in the fiddle for the whole morning and trying numerous combinations of the flex, width, min-width and max-width properties I definitely need you help! Thanks in advance!
I already have a Javascript workaround (counting columns and adding classes) but would much prefer a CSS-only solution.
I believe the answer is that what you're looking for is not possible with Flexbox. The reason is that the sizing algorithm (in simplified terms) uses a couple of steps to determine the actual size of the element:
Determine the preferred minimum size (the value of flex-basis if set to a length/percentage, the value of main axis size if declared to be auto, and min-content size if not). In your case, both .cell and .cell.wide prefer 120px.
Place items as if they had the preferred size.
Evaluate each resulting line (in a wrapping flex flow) and determine any remaining space.
Distribute remaining space (per line) according to flex-grow.
In your case, this means that each item (regardless if .wide or not) will evaluate to a preferred size of 120px, and thus fits 3 items on each row. At this point, the flex-grow factor does nothing, as there isn't any space left to grow, so the fact that .wide items have a flex-grow of 1 is irrelevant. I think your example would require a form of "sometimes min-width, sometimes not" behavior that flexbox just doesn't do — there would be too many layout passes for the browser to do (e.g. reflowing into lines several times etc).
The only CSS-based solution I can think of is to hardcode all the possible scenarios in something akin to "Quantity Queries", but that would get unwieldy fast...
Closest I can get with flexbox is something like https://jsfiddle.net/qde5xq09/1/.

How to center a div with Bootstrap2?

http://twitter.github.com/bootstrap/scaffolding.html
I tried like all combinations:
<div class="row">
<div class="span7 offset5"> box </div>
</div>
or
<div class="container">
<div class="row">
<div class="span7 offset5"> box </div>
</div>
</div>
changed span and offset numbers...
But I cant get a simple box perfectly centered on a page :(
I just want a 6-column-wide box centered...
edit:
did it with
<div class="container">
<div class="row" id="login-container">
<div class="span8 offset2">
box
</div>
</div>
</div>
But the box is too wide, is there any way I can do it with span7 ?
span7 offset2 gives extra padding to the left span7 offset3 extra padding to the right...
Bootstrap's spans are floated to the left. All it takes to center them is override this behavior. I do this by adding this to my stylesheet:
.center {
float: none;
margin-left: auto;
margin-right: auto;
}
If you have this class defined, just add it to the span and you're good to go.
<div class="span7 center"> box </div>
Note that this custom center class must be defined after the bootstrap css. You could use !important but that isn't recommended.
besides shrinking the div itself to the size you want, by reducing span size like so... class="span6 offset3", class="span4 offset4", etc... something as simple as style="text-align: center" on the div could have the effect you're looking for
you can't use span7 with any set offset and get the span centered on the page (Because total spans = 12)
Bootstrap3 has the .center-block class that you can use. It is defined as
.center-block {
display: block;
margin-left: auto;
margin-right: auto;
}
Documentation here.
If you want to go full-bootstrap (and not the auto left/right way) you need a pattern that will fit within 12 columns e.g. 2 blanks, 8 content, 2 blanks. That's what this setup will do.
It only covers the -md- variants, I tend to snap it to full size for small by adding col-xs-12
<div class="container">
<div class="col-md-8 col-md-offset-2">
box
</div>
</div>
Sounds like you just wanted to center align a single container.
The bootstrap framework might be overcomplicating that one example, you could have just had a standalone div with your own styling, something like:
<div class="login-container">
<!-- Your Login Form -->
</div>
and style:
.login-container {
margin: 0 auto;
width: 400px; /* Whatever exact width you are looking for (not bound by preset bootstrap widths) */
}
That should work fine if you are nested somewhere within a bootstrap .container div.
add the class centercontents
/** Center the contents of the element **/
.centercontents {
text-align: center !important;
}
#ZuhaibAli code kind of work for me but I changed it a little bit:
I created a new class in css
.center {
float: none;
margin-left: auto;
margin-right: auto;
}
then the div become
<div class="center col-md-6"></div>
I added col-md-6 for the width of the div itself which in this situation meant the div is half the size, there are 1 -12 col md in bootstrap.
Follow this guidance https://getbootstrap.com/docs/3.3/css/
Use .center-block
.center-block {
display: block;
margin-left: auto;
margin-right: auto;
}
wrap the div in a parent div with class row then add style margin:0 auto; to the div
<div class="row">
<div style="margin: 0 auto;">center</div>
</div>

Resources