Reputation: 12978
I'm trying to place the output
element above the slider for smaller screens, and to the right of the "+" button for the rest. How can I do this with flexbox, without duplicating markup? Changing the order with CSS seems to not have the wanted effect when I have a wrapper div, and without the wrapper div, I can't align the output
element above the slider.
Any ideas?
$("#minus").click(function(event) {
zoom("out");
});
$("#plus").click(function(event) {
zoom("in");
});
$("#range").on('input change', function(event) {
$('#output').text($(event.currentTarget).val());
});
function zoom(direction) {
var slider = $("#range");
var step = parseInt(slider.attr('step'), 10);
var currentSliderValue = parseInt(slider.val(), 10);
var newStepValue = currentSliderValue + step;
if (direction === "out") {
newStepValue = currentSliderValue - step;
} else {
newStepValue = currentSliderValue + step;
}
slider.val(newStepValue).change();
};
.container {
width: 100%;
margin: 50px auto;
display: flex;
justify-content: space-between;
align-items: center;
}
input[type=range] {
width: 100%;
}
button {
flex: 0 0 auto;
width: 40px;
height: 40px;
border-radius: 100%;
background: white;
font-size: 24px;
border: 1px solid lightgrey;
cursor: pointer;
-webkit-appearance: none;
margin: 0 10px;
}
.inner-wrap {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
#minus {
order: 1;
}
#range {
order: 1;
}
#output {
order: 1;
@media screen and (min-width: 320px) {
order: 5;
}
}
#plus {
order: 4;
}
.inner-wrap {
order: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<button id="minus">-</button>
<div class="inner-wrap">
<output for="range" id="output">50</output>
<input id="range" type="range" step="10" value="50">
</div>
<button id="plus">+</button>
</div>
$("#minus").click(function(event) {
zoom("out");
});
$("#plus").click(function(event) {
zoom("in");
});
$("#range").on('input change', function(event) {
$('#output').text($(event.currentTarget).val());
});
function zoom(direction) {
var slider = $("#range");
var step = parseInt(slider.attr('step'), 10);
var currentSliderValue = parseInt(slider.val(), 10);
var newStepValue = currentSliderValue + step;
if (direction === "out") {
newStepValue = currentSliderValue - step;
} else {
newStepValue = currentSliderValue + step;
}
slider.val(newStepValue).change();
};
.container {
width: 100%;
margin: 50px auto;
display: flex;
justify-content: space-between;
align-items: center;
}
input[type=range] {
width: 100%;
}
button {
flex: 0 0 auto;
width: 40px;
height: 40px;
border-radius: 100%;
background: white;
font-size: 24px;
border: 1px solid lightgrey;
cursor: pointer;
-webkit-appearance: none;
margin: 0 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<button id="minus">-</button>
<input id="range" type="range" step="10" value="50">
<button id="plus">+</button>
<output for="range" id="output">50</output>
</div>
Upvotes: 4
Views: 769
Reputation: 371221
Instead of using the order
property and nested containers, use absolute positioning. Here's a simplified version of your code. The media query uses absolute positioning to center the output
element in smaller screens.
.container {
display: flex;
align-items: center;
margin: 50px auto;
position: relative;
}
input[type=range] {
flex: 1;
min-width: 0;
}
button {
flex: 0 0 40px;
height: 40px;
border-radius: 100%;
background: white;
font-size: 24px;
border: 1px solid lightgrey;
cursor: pointer;
margin: 0 10px;
}
@media (max-width: 320px) {
#output {
position: absolute;
top: -15px;
left: 50%;
transform: translateX(-50%);
}
}
<div class="container">
<button id="minus">-</button>
<input id="range" type="range" step="10" value="50">
<button id="plus">+</button>
<output for="range" id="output">50</output>
</div>
For others who may be interested, here's an alternative: Put the output
element in both locations.
Control their appearance with display: none
in the media query.
Something like this:
@media screen and (min-width: 320px) {
#output-small-screen { display: none }
}
@media screen and (max-width: 320px) {
#output-wide-screen { display: none }
}
.container {
width: 100%;
margin: 50px auto;
display: flex;
justify-content: space-between;
align-items: center;
}
input[type=range] {
width: 100%;
}
button {
flex: 0 0 auto;
width: 40px;
height: 40px;
border-radius: 100%;
background: white;
font-size: 24px;
border: 1px solid lightgrey;
cursor: pointer;
-webkit-appearance: none;
margin: 0 10px;
}
.inner-wrap {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
#minus {
order: 1;
}
#range {
order: 1;
}
#output-wide-screen {
order: 5;
}
@media screen and (min-width: 320px) {
#output-small-screen {
display: none
}
}
@media screen and (max-width: 320px) {
#output-wide-screen {
display: none
}
}
#plus {
order: 4;
}
.inner-wrap {
order: 2;
}
<div class="container">
<button id="minus">-</button>
<div class="inner-wrap">
<output for="range" class="output" id="output-small-screen">50</output>
<input id="range" type="range" step="10" value="50">
</div>
<button id="plus">+</button>
<output for="range" class="output" id="output-wide-screen">50</output>
</div>
Upvotes: 2