How to change margin size based on screen size breakpoints? - html

I have a row of reactstrap cards that are dynamically placed in rows, and for "md" screen sizes and up (bootstrap), there will be 3 cards per row, and for lower it'll be 2 cards.
Here's the component:
<Card
outline
as='a'
style={{ cursor: 'pointer', margin: '1rem' }}
>
<CardImg top width='100%' src={img}' />
<CardBody>
<CardTitle tag='h5'>{this.props.title}</CardTitle>
</CardBody>
</Card>
My problem is, I want only the middle card to have margins on the sides (marginLeft: '1rem', marginRight: '1rem').
Since the number of cards in a row changes based on screensize, I can't just say "if it's a multiple of x, then have this style". Unless I know the screensize, so is there a way to create a prop in my parent component that I can pass into my card component to let it know what to set the margin as?
Thanks
(Any better suggestions are welcome)
More code:
render () {
return (
...
<div className='row' style={{margin:'0rem'}}>
{
disp.map((d, index) => {
return (
<div className='col-md-4 col-6 d-flex'>
<the card component here>
</div
)
...
}
}
</div>
....

If you want space in between the children then you can use gap and using flexbox. But gap property doesn't have great support.
html, body{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.card-container {
background-color: aquamarine;
display: flex;
flex-direction: column;
gap: 1rem;
}
.card {
border: 1px solid grey;
padding: 1rem;
height: 100px;
}
#media only screen and (min-width: 600px) {
.card-container {
flex-direction: row;
}
.card {
flex: 1;
}
}
<div class="card-container">
<div class="card">card1</div>
<div class="card">card1</div>
<div class="card">card1</div>
</div>
So you can use
[parent-selector] > * + *
Above selector means select all children that are siblings of any element and which is direct child of parent-selector(use class for parent or HTML element).
If the structure is from top to bottom or in row view then you can use
.card-container > * + * {
margin-top: 1rem;
}
and if you want space in between when the elements are arrange in left to right or in columns then use
.card-container > * + * {
margin-left: 1rem;
}
html, body{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.card-container {
background-color: aquamarine;
display: flex;
flex-direction: column;
}
.card {
border: 1px solid grey;
padding: 1rem;
height: 100px;
}
.card-container>*+* {
margin-top: 1rem;
}
#media only screen and (min-width: 600px) {
.card-container {
flex-direction: row;
}
.card {
flex: 1;
}
.card-container>*+* {
margin-top: 0;
margin-left: 1rem;
}
}
<div class="card-container">
<div class="card">card1</div>
<div class="card">card1</div>
<div class="card">card1</div>
</div>

"How to change margin size based on screen size breakpoints?"
That's exactly what the Bootstrap responsive spacing classes are used for. But, if you're using the grid (Row > Col) it's better to use padding (not margins) to adjust the spacing between columns.
Assuming you're using the column classes col-6 col-md-4 to get "for "md" screen sizes and up, there will be 3 cards per row, and for lower it'll be 2 cards."...
You can responsively adjust the padding on the columns, or the margin in the cards. For example, here's 3 margin units on md and up (mx-md-3), and 1 margin unit (mx-1) on lower:
<Col className="col-6 col-md-4 py-3">
<Card className="mx-1 mx-md-3">
...
</Card>
</Col>
React on Codeply

Related

How do I create 2 column divs that stack on top of each at different screen sizes?

The div container is breaking my page. It's overriding a container used elsewhere. Is there any other alternative I can use to still have the same effect i.e the div columns sit next to each but at different screen resolutions, they stack on top of each other, and both retain equal width and length as they shrink?
How do I create two responsive divs that sit next to each other and stack on top of each other at different screen sizes? The dimensions are specific (each div is 350 x 217 px).
One div will have a text centred horizontally within the div but also left aligned and the other will be an image.
Below is the ideal end result. I'm a newbie to dev and this is for an assignment that's overdue. I've been fiddling around for the past couple of days and I keep going round in circles.
Responsive view on smaller screens:
* {
box-sizing: border-box;
}
.column {
flex: 1;
}
.left {
background-color: #e0e620;
}
.center {
margin: auto;
border: 3px solid green;
padding: 50px 50px;
}
.right {
background-color: #E5E5E5;
}
.row {
display: flex;
}
img {
width: 100%;
display: block;
}
#media screen and (max-width: 600px) {
.row {
width: 100vw;
display: block;
}
<div class="row">
<div class="column left">
<div class="center">The Info.<br />
<a class="link-button-green" href="" title="Info
guide">Download now</a>
</div>
</div>
<div class="column right">
<img src="https://via.placeholder.com/350x217.jpg">
</div>
</div>
The image is 350 x 217. Here is the ideal look below:
The below screen is what I would like to achieve without changing the existing width and height of yellow div? How do I go about achieving that?
add display: grid to the parent element .row;
add grid-template-columns: 1fr 1fr to the parent element (.row) to have a 2-column layout.
For screens at 600px or below you change the grid-template-columns to 1fr for the element .row to get a 1-column layout. To have both elements have the same height, you can use grid-auto-rows: 1fr on the parent element.
To maintain the normal block-level-behavior you add display: flex; flex-direction: column to the .left column. Flexbox will allow you do vertical center the text.
To vertical center the text you have to align it to the main-axis (flex-direction: column) with justify-content: center
* {
box-sizing: border-box;
}
.row {
display: grid;
grid-template-columns: 1fr 1fr;
}
#media only screen
and (max-width: 600px) {
.row {
grid-template-columns: 1fr;
grid-auto-rows: 1fr;
}
}
.left {
background-color: yellow;
display: flex;
flex-direction: column;
justify-content: center;
}
img {
width: 100%;
display: block;
object-fit: contain;
}
<div class="row">
<div class="column left">
<div class="center">The Info.<br />
<a class="link-button-green" href="" title="Info
guide">Download now</a>
</div>
</div>
<div class="column right">
<img src="https://via.placeholder.com/350x217.jpg">
</div>
</div>
Your question needs work.
You want the specific div widths to be 350px x 217px, but when you get to a min-width of 600px, that width of 350px isn't going to work anymore. You will struggle to have a responsive page if you set explicit heights and widths. You need to let elements fill their spaces naturally.
That said, I've created a solution that I think would work best based on the images you've provided.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
img {
max-width: 100%;
height: auto;
}
.container {
display: flex;
flex-direction: column;
}
#media screen and (min-width: 600px) {
.container {
flex-direction: row;
min-height: 217px;
}
}
.inner {
background-color: #E0E61F;
display: flex;
justify-content: center;
align-items: flex-start;
flex-direction: column;
width: 100%;
min-height: 217px;
}
.inner span {
padding-left: 1rem;
min-height: unset;
}
.inner img {
min-height: 217px;
object-fit: cover;
}
<div class="container">
<div class="inner">
<span>The Info</span>
<span>Download Now</span>
</div>
<div class="inner">
<img src="https://placekitten.com/1600/900" alt="">
</div>
</div>
Like mentioned above i would start with mobile view. You can create a parent div around your two boxes called container with the following css properties
display:flex
flex-direction: column
Then add a media query set at the width you would like this divs to be side by side and change the flex direction on your container div to row
flex-direction: row

I have a flexbox with 2 columns, can I make the second column go under the first one under certain dimension?

As you can see in the snippet, I have 2 columns, however, I want to make it so that the red column goes under the blue one ( and they both take 100% of the parent width ) when the browser becomes less than 1200px.
Now if I were using 2 inline-block elements I would just create a media query that would make both elements block, however, now that I'm trying to use flexbox, I'm not sure how to do this.
.specific-image-container {
display: flex;
position: relative;
width: 100%;
}
.specific-image-column {
flex: 4;
background-color: blue;
}
.more-images-column {
flex: 1;
background-color: red;
}
.content {
height: 300px;
}
<div class="specific-image-container">
<div class="specific-image-column">
<div class='content'>s</div>
</div>
<div class="more-images-column">
<div class='content'>s</div>
</div>
</div>
Set flex-direction to column within a media query
#media all and (max-width: 1200px) {
.specific-image-container {
flex-direction: column;
}
}

Changing the order of elements and wrap after specific element with flexbox

I'm trying to create this structure using only flexbox.
This is how my html looks like.
<div class="container">
<div class="first_container"></div>
<div class="second_container"></div>
<div class="third_container"></div>
</div>
I know it's really basic problem if i could just change divs order or add additional wrapper for the first line. The problem is it have to stay as it is.
Basic dimensions:
1. first_container - should takes 100% minus third_container width
2. second_container - shoudl takes 100%
I am asking for some tips, because my hands are slowly falling.
You can use flexbox order property
* {
box-sizing: border-box;
}
.container {
display: flex;
flex-wrap: wrap;
}
.container div {
padding: 10px;
border: 5px solid #fff;
background: gray;
text-align: center;
}
.first_container {
width: 70%;
order: 1;
}
.second_container {
width: 100%;
order: 3;
}
.third_container {
width: 30%;
order: 2;
}
<div class="container">
<div class="first_container">1</div>
<div class="second_container">2</div>
<div class="third_container">3</div>
</div>

Problems building a flexbox grid

I'm trying to build myself a flexbox with the following design:
My html looks like this (and I would like to NOT change this):
<div class="wrapper">
<div class="page-header">Heading</div>
<h3 class="right_1">right_1</h3>
<div class="right_2">right_2</div>
<div class="left">form element</div>
<h3 class="right_3">right_3</h3>
<div class="right_4">right_4</div>
</div>
This is the standard layout of the joomla contact page. I want to change the design though without altering html/php code.
Is that possible using flexbox?
And can I use #media queries to make right_1 - right_4 to move under left on mobile view (< 800px or example)?
I myself cannot get it to work, I always end up with right_1 - right_4 next to each other instead of them stacking to the total height of the left portion.
The layout you want cannot be achieved with flexbox. The reasons are explained here:
Is it possible for flex items to align tightly to the items above them?
However, the layout is relatively simple with CSS Grid.
There are, in fact, multiple methods for building the layout with Grid. I'll use the grid-template-areas property, which allows you to lay out your elements using ASCII art.
.wrapper {
display: grid;
height: 100vh;
grid-template-columns: 1fr 1fr;
grid-template-areas:
" heading heading "
" left_ right1 "
" left_ right2 "
" left_ right3 "
" left_ right4 "
}
.page-header { grid-area: heading; }
.right_1 { grid-area: right1; }
.right_2 { grid-area: right2; }
.right_3 { grid-area: right3; }
.right_4 { grid-area: right4; }
.left { grid-area: left_; } /* "left" is a pre-defined CSS keyword,
so it may not work */
#media ( max-width: 800px ) {
.wrapper {
grid-template-columns: 1fr;
grid-template-areas:
" heading "
" left_ "
" right1 "
" right2 "
" right3 "
" right4 "
}
}
/* non-essential decorative styles */
.page-header { background-color: red; }
.right_1 { background-color: chartreuse; }
.right_2 { background-color: aqua; }
.right_3 { background-color: skyblue; }
.right_4 { background-color: black; color: white; }
.left { background-color: cornsilk; }
body { margin: 0; }
.wrapper > * {
font-weight: bold;
font-size: 1.5em;
border: 1px solid black;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
<div class="wrapper">
<div class="page-header">Heading</div>
<h3 class="right_1">right_1</h3>
<div class="right_2">right_2</div>
<div class="left">form element</div>
<h3 class="right_3">right_3</h3>
<div class="right_4">right_4</div>
</div>
jsFiddle demo
In essence, here's how it works:
We establish a block-level grid with display: grid.
With grid-template-columns: 1fr 1fr we are telling the grid to create two columns. The fr unit tells the container to consume available space. It's similar to flexbox's flex-grow property. So both columns will share the full width of the container.
The grid-template-areas property allows you to lay out named grid areas (that you have defined) to create a visual representation of your layout using ASCII art.
In the media query for smaller screens, we remove one column and re-order the grid areas.
Browser Support for CSS Grid
Chrome - full support as of March 8, 2017 (version 57)
Firefox - full support as of March 6, 2017 (version 52)
Safari - full support as of March 26, 2017 (version 10.1)
Edge - full support as of October 16, 2017 (version 16)
IE11 - no support for current spec; supports obsolete version
Here's the complete picture: http://caniuse.com/#search=grid
Here is one way to solve that, based on the existing markup and CSS Flexbox.
The left needs to be absolute positioned for desktop view and the page-header need a fixed height.
If you don't want to set a fixed height, you'll need a script that takes care of the height calculation
html, body {
margin: 0;
}
.wrapper {
position: relative;
display: flex;
flex-direction: column;
min-height: 100vh;
}
.wrapper * {
padding: 0 10px;
margin: 0;
border: 1px solid black;
box-sizing: border-box;
}
.page-header {
height: 70px;
width: 100%;
background: red;
}
.right_1, .right_2, .right_3, .right_4 {
flex: 1;
width: 50%;
margin-left: 50%;
background: lightblue;
}
.left {
position: absolute;
left: 0;
top: 70px;
width: 50%;
min-height: calc(100vh - 70px);
background: yellow;
}
#media only screen and (orientation: portrait) {
.wrapper * {
width: 100%;
margin: 0;
}
.left {
position: static;
flex: 1;
min-height: auto;
order: -1
}
.page-header {
order: -2;
}
}
<div class="wrapper">
<div class="page-header">Heading</div>
<h3 class="right_1">right_1</h3>
<div class="right_2">right_2</div>
<div class="left">form element</div>
<h3 class="right_3">right_3</h3>
<div class="right_4">right_4</div>
</div>
Probably the easiest way to change the order of div elements, you can use Jquery for this purpose. For example:
$("#element1").before($("#element2"));
Eventually:
CSS:
#blocks {
display: box;
box-orient: vertical;
}
#b1 {
box-ordinal-group: 2;
}
#b2 {
box-ordinal-group: 3;
}
HTML:
<div id="blocks">
<div id="b1">Block 1</div>
<div id="b2">Block 2</div>
<div id="b3">Block 3</div>
</div>
It should work.

CSS flexbox - is there a better way to do this?

The result I'm looking for is one big block on the left, and then four small blocks on the right, and everything aligns.
I managed to do this in this fiddle but my solution has a couple of problems:
- it's not very clean in terms of code
- it's not responsive
HTML:
<div class="wrapper">
<div class="box big">ONE</div>
<div class="med-wrapper">
<div class="row-1">
<div class="box medium">TWO</div>
<div class="box medium">THREE</div>
</div>
<div class="row-2">
<div class="box medium">FOUR</div>
<div class="box medium">FIVE</div>
</div>
</div>
</div>
CSS:
.wrapper {
display: flex;
flex-direction: row;
flex-flow: row wrap;
justify-content: space-around;
height: 200px;
}
/* #media screen and (max-width: 768px) {
flex-direction: column
} */
.box {
background: #09f;
color: white;
padding: 1em;
margin: 5px;
text-align: center;
}
.big {
flex: 5;
}
.medium {
flex: 5;
height: 100px;
}
.med-wrapper {
display: flex;
}
Also, you might notice that I have set the flex on both .big and .medium to 5, because I want the total width of the big box and the total width of two medium boxes to be equal, but it didn't work.
Is there a better way to do this?
It's tricky to have everything to align without getting into a lot of constraints, but using flexbox wrapping in the column direction on the right part could work.
Here's a quick version that uses a flex-flow: column wrap on the right part (.med-wrapper) and gets rid of the wrapper element on the two column wrappers inside it -
<div class="wrapper">
<div class="box big">
ONE
</div>
<div class="med-wrapper">
<div class="box medium">TWO</div>
<div class="box medium">THREE</div>
<div class="box medium">FOUR</div>
<div class="box medium">FIVE</div>
</div><!-- /.med-wrapper -->
</div><!-- /.wrapper -->
...and then the CSS:
body {
font-family: 'calibri', sans-serif;
margin: 0;
}
.wrapper {
display: flex;
justify-content: space-around;
height: 200px;
}
.box {
background: #09f;
color: white;
padding: 1em;
margin: 0 5px;
text-align: center;
box-sizing: border-box;
}
.big {
flex: 1;
height: 100%;
}
.med-wrapper {
flex: 1;
display: flex;
height: 100%;
flex-flow: column wrap;
justify-content: space-between;
overflow: auto;
}
.medium {
/* exact sizing for the medium boxes (i.e. get it from main sizing.) */
flex: 0 0 auto;
/* adjust for margins: */
width: calc(50% - 10px);
height: calc(50% - 5px);
}
/* some theoretical adjustments for smaller screens */
#media screen and (max-width: 768px) {
/* switch the wrapper to column dir, and remove fixed height. */
.wrapper {
flex-direction: column;
height: auto;
}
/* just a min height for demo purposes. */
.big {
min-height: 200px;
}
/* Now we need to re-set a height on this one, if we
want to keep the 2x2 square thing. */
.med-wrapper {
margin-top: 10px;
height: 200px;
}
}
Live demo at http://jsbin.com/kasez/5/edit
I've used calc()for the size calculations to counter margins, but hey, if you're already depending on flexbox, you probably need a fallback anyway. :-)
It should work with just the one explicit height on the .wrapper element, but the rest of the items should adjust accordingly - the downside is that overflow handling gets hard.
This is, incidentally, the type of "2D" situation (vs flexbox's 1D) that Grid Layout is meant to help with, but it'll be a while before that is a viable option.