I'm trying to design a component in which you could change the width proportions of two blocks by moving a slider left and right:
codpen and demo:
.outer {
display: flex;
flex-direction: row;
}
.block {
height: 200px;
width: -webkit-calc(50% - 5px);
width: -moz-calc(50% - 5px);
width: calc(50% - 5px);
}
.block-1 {
background-color: red;
}
.block-2 {
background-color: green;
}
.slider {
line-height: 100%;
width: 10px;
background-color: #dee2e6;
border: none;
cursor: e-resize;
}
<div id="app">
<div class="outer">
<div class="block block-1">
Block 1
</div>
<div class="slider">
S<br>l<br>i<br>d<br>e<br>r
</div>
<div class="block block-2">
Block 2
</div>
</div>
</div>
I have tried using draggable-vue-directive
and change the width of blocks based on slider position.
However, it didn't work really well, since draggable-vue-directive
set the slider to position:fixed
which in turn messed up the block alignment.
How can I make the .slider
block horizontally draggable without setting position:fixed
?
How to correctly resize Block1
and Block2
when slider moves?
Note: I'm not using jQuery
You can adjust your flexbox along with resize
- the downside is that the slider its not very customizeable:
resize: horizontal
to one of the flex itemsflex: 1
to the other flex item (so that this flex item will adjust automatically in response to the changing width of the other flex item as it is resized)See demo below:
.outer {
display: flex;
flex-direction: row;
}
.block {
height: 100px;
width: 50%; /* 50% would suffice*/
}
.block-1 {
background-color: red;
resize: horizontal; /* resize horizontal */
overflow: hidden; /* resize works for overflow other than visible */
}
.block-2 {
background-color: green;
flex: 1; /* adjust automatically */
}
<div id="app">
<div class="outer">
<div class="block block-1">
Block 1
</div>
<div class="block block-2">
Block 2
</div>
</div>
</div>
So we'll use vanilla JS instead of the resize solution above:
mousedown
listener that registers a mousemove
listener that updates the block-1
width (and reset the mouseup
event)min-width: 0
to override min-width: auto
of the block-2
elementSee demo below:
let block = document.querySelector(".block-1"),
slider = document.querySelector(".slider");
slider.onmousedown = function dragMouseDown(e) {
let dragX = e.clientX;
document.onmousemove = function onMouseMove(e) {
block.style.width = block.offsetWidth + e.clientX - dragX + "px";
dragX = e.clientX;
}
// remove mouse-move listener on mouse-up
document.onmouseup = () => document.onmousemove = document.onmouseup = null;
}
.outer {
display: flex;
flex-direction: row;
}
.block {
height: 100px;
width: 50%; /* 50% would suffice*/
}
.block-1 {
background-color: red;
}
.block-2 {
background-color: green;
flex: 1; /* adjust automatically */
min-width: 0; /* allow flexing beyond auto width */
overflow: hidden; /* hide overflow on small width */
}
.slider {
line-height: 100%;
width: 10px;
background-color: #dee2e6;
border: none;
cursor: col-resize;
user-select: none; /* disable selection */
text-align: center;
}
<div id="app">
<div class="outer">
<div class="block block-1">
Block 1
</div>
<div class="slider">
S<br>l<br>i<br>d<br>e<br>r
</div>
<div class="block block-2">
Block 2
</div>
</div>
</div>
You can adapt the above into Vue easily without using any custom Vue plugins for this - the changes are:
@mousedown
listener on slider
that triggers the slider
use of refs
to update the width of block-1
See demo below:
new Vue({
el: '#app',
data: {
block1W: '50%'
},
methods: {
drag: function(e) {
let dragX = e.clientX;
let block = this.$refs.block1;
document.onmousemove = function onMouseMove(e) {
block.style.width = block.offsetWidth + e.clientX - dragX + "px";
dragX = e.clientX;
}
// remove mouse-move listener on mouse-up
document.onmouseup = () => document.onmousemove = document.onmouseup = null;
}
}
});
.outer {
display: flex;
flex-direction: row;
}
.block {
height: 100px;
width: 50%; /* 50% would suffice*/
}
.block-1 {
background-color: red;
}
.block-2 {
background-color: green;
flex: 1; /* adjust automatically */
min-width: 0; /* allow flexing beyond auto width */
overflow: hidden; /* hide overflow on small width */
}
.slider {
line-height: 100%;
width: 10px;
background-color: #dee2e6;
border: none;
cursor: col-resize;
user-select: none; /* disable selection */
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="outer">
<div class="block block-1" ref="block1" :style="{'width': block1W}">
Block 1
</div>
<div class="slider" @mousedown="drag">
S<br>l<br>i<br>d<br>e<br>r
</div>
<div class="block block-2">
Block 2
</div>
</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With