Reputation: 6633
I am attempting to make a row of buttons responsive. There can be either 3 or 2 buttons in the row. The reason I'm thinking flexbox (or maybe grid) is the solution is because the text in the buttons is internationalized and the language will vary meaning they will wrap depending on the text in the buttons, not just the screen width so I can't just write media queries that correspond to screen width.
These are the initial states with no wrapping: The starting states (no wrapping) are either of these images (depending on 2 or 3 buttons):
These are the desired wrapping states when the container gets too small:
I created a fiddle that allows you to adjust the width of the box and toggle the optional button here:
See Fiddle here to test each variant
This is the starting html, but maybe it would help to wrap the first two buttons together
<div class="container">
<div class="button button1">
This is a longer button
</div>
<div class="button button2">
Optional Button
</div>
<div class="button button3">
Confirmation button
</div>
</div>
<button class="width-button">Toggle width</button>
<button class="toggle-button-button">Toggle optional button</button
>
Upvotes: 2
Views: 1555
Reputation: 272909
And idea using flexbox. Resize both containers to see the result
.container {
width: 480px;
background-color: lightgray;
margin: 40px 0;
padding: 12px;
overflow:hidden;
resize:horizontal;
display:flex;
flex-wrap:wrap;
z-index:0;
position:relative;
}
.button {
padding: 12px;
background-color: green;
display: inline-block;
border-radius: 8px;
margin:2px;
position:relative;
}
.button3 {
flex-grow:1; /* grow on wrap */
order:2; /* put after the pseudo element*/
}
/* this will push the confirmation button
and will complete the first button on wrap */
.container::after {
content:"";
flex-grow:999; /* push the last button */
flex-basis:1px;
background:green;
border-radius:8px;
position:relative;
margin:2px 2px 2px -20px;
z-index:-3;
}
/* hide the pseudo element when confirmation button on the first row */
.button3::before {
content:"";
position:absolute;
z-index:-1;
top:0;
bottom:0;
right:100%;
width:100vw;
background:lightgray;
}
/* make sure the button area is big enough for the events*/
.button::after {
content:"";
position:absolute;
z-index:-2;
top:0;
bottom:0;
left:100%;
width:100vw;
}
<div class="container">
<div class="button button1">
This is a longer button
</div>
<div class="button button2">
Optional Button
</div>
<div class="button button3">
Confirmation button
</div>
</div>
<div class="container">
<div class="button button1">
This is a longer button
</div>
<div class="button button2" style="display:none;">
Optional Button
</div>
<div class="button button3">
Confirmation button
</div>
</div>
Upvotes: 0
Reputation: 60563
If your layout is fixed and you are really using the .narrow
class you can do like this,
document.querySelector('.width-button').addEventListener('click', () => {
document.querySelector('.container').classList.toggle('narrow');
});
document.querySelector('.toggle-button-button').addEventListener('click', () => {
document.querySelector('.button1').classList.toggle('hide');
});
.container {
width: 580px;
background-color: lightgray;
margin: 40px 0;
padding: 12px;
transition: width 200ms ease-in-out;
display: flex;
flex-wrap: wrap;
}
.container.narrow {
width: 320px;
}
.button {
padding: 12px;
background-color: green;
display: inline-block;
border-radius: 8px;
margin: 5px
/* demo */
}
.button1.hide+.button2 {
display: none;
}
.button3 {
margin-left: auto;
}
.container.narrow .button1.hide,
.container.narrow .button3 {
flex: 0 100%;
}
<div class="container">
<div class="button button1">
This is a longer button
</div>
<div class="button button2">
Optional Button
</div>
<div class="button button3">
Confirmation button
</div>
</div>
<button class="width-button">Toggle width</button>
<button class="toggle-button-button">Toggle optional button</button>
otherwise you can change the .narrow
class with media queries, something like this:
document.querySelector('.toggle-button-button').addEventListener('click', () => {
document.querySelector('.button1').classList.toggle('toggle');
});
body {
margin: 0
}
.container {
width: 100%;
background-color: lightgray;
margin: 40px 0;
padding: 12px;
box-sizing: border-box;
transition: width 200ms ease-in-out;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
@media (min-width: 600px) {
.container {
justify-content: flex-start
}
}
.button {
padding: 12px;
background-color: green;
display: inline-block;
border-radius: 8px;
/* demo */
margin: 5px;
}
.toggle+.button2 {
display: none;
}
.button1.toggle {
flex: 1;
}
@media (min-width: 600px) {
.button1.toggle{
flex: 0 auto;
}
}
.button3 {
flex: 0 100%;
}
@media (min-width: 600px) {
.button3 {
margin-left: auto;
flex: 0 auto;
}
}
<div class="container">
<div class="button button1">
This is a longer button
</div>
<div class="button button2">
Optional Button
</div>
<div class="button button3">
Confirmation button
</div>
</div>
<button class="toggle-button-button">Toggle optional button</button>
Upvotes: 1