Reputation: 109
I'm trying to create a User Entry Form with multiple fields/values in a table format. If its a desktop, it should show 6 columns (a pair of field name/value each) and if its a phone (portrait mode) should show just 2. If it's in landscape show 4 columns.
Expected output: Phone (Portrait)
+--------+---------+
+ Field + Value +
+--------+---------+
+ Field + Value +
+--------+---------+
+ Field + Value +
+--------+---------+
Phone (Landscape mode)
+--------+---------+--------+---------+
+ Field + Value + Field + Value +
+--------+---------+--------+---------+
+ Field + Value + Field + Value +
+--------+---------+--------+---------+
+ Field + Value + Field + Value +
+--------+---------+--------+---------+
iPad or larger
+--------+---------+--------+---------+--------+---------+--------+---------+
+ Field + Value + Field + Value + Field + Value + Field + Value +
+--------+---------+--------+---------+--------+---------+--------+---------+
+ Field + Value + Field + Value + Field + Value + Field + Value +
+--------+---------+--------+---------+--------+---------+--------+---------+
I want it to be pure CSS (as much as possible) as the content will be filled by an angular constructor later.
However, I'm not getting the correct flow as the divs seem to stick together and not break away clean as a row! Probably I'm missing something here. It works fine in the phone portrait mode but as you can see in the pen below, it's all over the place.
Code Pen: Link
Here is the code so far:
<div class='table-type'>
<div class='row-type'>
<div class='cell-type'>Account</div>
<div class='cell-type'>Acme Incorporated US and Seychelles</div>
<div class='cell-type'>Geography</div>
<div class='cell-type'>North America</div>
<div class='cell-type'>Premier</div>
<div class='cell-type'>Yes</div>
<div class='cell-type'>Countact Count</div>
<div class='cell-type'>23</div>
<div class='cell-type'>Account Manager</div>
<div class='cell-type'>Dustin Brown</div>
<div class='cell-type'>Customer Engineer</div>
<div class='cell-type'>David Hoff</div>
<div class='cell-type'>Exec Sponsor</div>
<div class='cell-type'>Jeff Larabee</div>
</div>
</div>
Now the CSS:
.table-type
{
display: table;
margin-bottom: 5px;
width:100%;
table-layout: fixed;
}
.row-type
{
display: table-row;
}
.cell-type
{
float: left;
margin-top: 2px;
margin-bottom: 2px;
padding: 5px;
line-height: 16px;
font-family: 'Lato', sans-serif;
border: 4px solid;
border-color: #fff;
border-radius: 15px;
border-spacing: 15px 15px;
}
.cell-type:nth-child(odd)
{
text-align: right;
}
.cell-type:nth-child(even)
{
text-align:left;
font-weight: bold;
-webkit-border-radius:15px;-moz-border-radius:15px;
background-color: #e3f2f2;
}
@media (max-width: 500px)
{
.cell-type:nth-child(3n+3)
{
display: block;
}
.cell-type:nth-child(odd)
{
width:30%;
}
.cell-type:nth-child(even)
{
width:70%;
}
}
@media (max-width: 700px) and (min-width: 501px)
{
.cell-type:nth-child(odd)
{
width:20%;
}
.cell-type:nth-child(even)
{
width:30%;
}
.cell-type:nth-child(5n+5)
{
display: block;
}
}
@media (min-width: 701px)
{
.cell-type:nth-child(odd)
{
width:13%;
}
.cell-type:nth-child(even)
{
width:20%;
}
.cell-type:nth-child(7n+7)
{
display: block;
}
}
Upvotes: 1
Views: 840
Reputation: 90287
I think it will be easier to achieve desired outcome using flexbox
:
.row-type {
display: flex;
flex-wrap: wrap;
}
.cell-type {
flex: 0 0 10%
/* translates to: flex-grow: 0;
* flex-shrink: 0;
* flex-basis: 10%;
*/
}
.cell-type:nth-child(even) {
flex-basis: 15%;
/* 10% + 15% = 25% */
}
But the first problem you need fixing is to apply box-sizing:border-box
to all your cells. This will change the way padding and border are taken into account, to be included in the width
property (or flex-basis
for flexbox), so you don't have to set percentages and deduct padding and border sizes.
Then, it's just a matter of laying out correct sizes of your cells based on parent width. In order to do it, pick a direction (from large to small or from small to large). I picked from large to small below, but doing it from small to large works as well.
Write the rules for your first picked interval outside of any @media
query before the @media
queries (this is important because the selectors inside your @media
queries will have equal specificity to ones outside and the rules inside @media
will apply solely on the fact they are placed later in CSS).
Remember: @media
queries do not change specificity. They only set whether or not the rules inside apply based on the provided condition.
So the rules set before the @media
queries will only apply when none of your subsequent @media
queries (overriding them) are true.
Then, using the same exact selectors, write your rules for the next interval, inside the appropriate @media
rule and continue until you get to the last @media
rule. You only need to overwrite the property that changes, which in this case is flex-basis
. In the case of tables it would be width
.
I also happen to believe your breakpoints are a bit off, as 700px
and 500px
are way too low as breaking points for your table (I decided to break them from 8 to 6/row at 1200px
, from 6 to 4/row at 950px
and from 4 to 2/row at 650px
). Feel free to disagree and adjust them according to your own needs and liking.
Here it is:
.table-type {
margin-bottom: 5px;
width: 100%;
}
.row-type {
display: flex;
flex-wrap: wrap;
align-items: stretch; /* you might also try `center` here */
}
.cell-type {
display: block;
flex: 0 0 10%;
margin: 3px 0;
padding: 7px 12px;
line-height: 16px;
min-height: 46px; /* added for equal height cells. removed on mobile */
font-family: 'Lato', sans-serif;
border-radius: 16px;
box-sizing: border-box;
}
.cell-type:nth-child(odd) {
text-align: right;
}
.cell-type:nth-child(even) {
flex-basis: 15%;
font-weight: bold;
background-color: #eaf5f5;
box-shadow: inset 0 1px 3px rgba(0,0,0,.06), inset 0 1px 1px rgba(0,0,0,.04), inset 0 2px 1px rgba(0,0,0,.03)
}
@media(max-width: 1200px) {
.cell-type:nth-child(odd) {
flex-basis: 13.3333%;
}
.cell-type:nth-child(even) {
flex-basis: 20%;
}
}
@media(max-width: 950px) {
.cell-type:nth-child(odd) {
flex-basis: 20%;
}
.cell-type:nth-child(even) {
flex-basis: 30%;
}
}
@media(max-width: 650px) {
.cell-type {
min-height:0;
}
.cell-type:nth-child(odd) {
flex-basis: 40%;
}
.cell-type:nth-child(even) {
flex-basis: 60%;
}
}
<div class='table-type'>
<div class='row-type'>
<div class='cell-type'>Account</div>
<div class='cell-type'>Acme Incorporated US and Seychelles</div>
<div class='cell-type'>Geography</div>
<div class='cell-type'>North America</div>
<div class='cell-type'>Premier</div>
<div class='cell-type'>Yes</div>
<div class='cell-type'>Countact Count</div>
<div class='cell-type'>23</div>
<div class='cell-type'>Account Manager</div>
<div class='cell-type'>Dustin Brown</div>
<div class='cell-type'>Customer Engineer</div>
<div class='cell-type'>David Hoff</div>
<div class='cell-type'>Exec Sponsor</div>
<div class='cell-type'>Jeff Larabee</div>
</div>
</div>
This can also be achieved with box model (using floats
). Do note display:table
(and it's related props for sub-elements) and box-model
do not play nice together. And by that I mean: to make cells wrap where you want them, you need either one of:
display:table-row
(that's how table model works).display:block
on both row and cell and float:left
on cells. This technique also needs clearing after correct end of row cell, to avoid cells floating at the wrong position when you have height differences between cells.Upvotes: 1
Reputation: 1646
Is this what you want?
.row-type
{
display: grid;
justify-items: center;
align-items: center;
}
...
@media (max-width: 500px)
{
.row-type{
grid-template-columns: repeat(2,1fr);
}
}
@media (max-width: 700px) and (min-width: 501px)
{
.row-type{
grid-template-columns: repeat(4,1fr);
}
}
@media (min-width: 701px)
{
.row-type{
grid-template-columns: repeat(8,1fr);
}
}
https://codepen.io/smollet777/pen/mzypJo?editors=0100
Upvotes: 1