How can I resize a DIV by dragging just ONE side of it?
Asked Answered
S

9

50

Let me be more specific... I don't want the DIV to resize WHILE I'm dragging. I want to drag it out (and maybe a vertical line follows my cursor) and when I release, it resizes the div.

Success answered 2/6, 2011 at 18:56 Comment(0)
A
21

There is a much simpler way to achieve this. CSS 3 has a resize property to make an HTML element resizeable, while following other CSS properties like min/max widths etc.

.resizeable {
  resize: both;
  overflow: auto;
  border: 2px solid black;
}

For more info, here are the MDN Docs on the resize CSS 3 property.

Afterimage answered 23/5, 2020 at 18:17 Comment(1)
That is useful, but would be more helpful if you could make the whole side draggable. So, in the case of a navigation menu on the left of my screen, I might want to drag the right border of that to resize the space the menu has. This solution puts the resize control in the lower right corner, but I'm worried my users won't see it there at the bottom of the screen. (My div extends the full height of the window.)Prichard
A
43

Have a look at this example

Html

<div id="sidebar">
     <span id="position"></span>
    <div id="dragbar"></div>
    sidebar
</div>
<div id="main">
    main
</div>

jquery

var dragging = false;
$('#dragbar').mousedown(function(e){
   e.preventDefault();

   dragging = true;
   var main = $('#main');
   var ghostbar = $('<div>',
                    {id:'ghostbar',
                     css: {
                            height: main.outerHeight(),
                            top: main.offset().top,
                            left: main.offset().left
                           }
                    }).appendTo('body');

    $(document).mousemove(function(e){
      ghostbar.css("left",e.pageX+2);
   });
});

$(document).mouseup(function(e){
   if (dragging) 
   {
       $('#sidebar').css("width",e.pageX+2);
       $('#main').css("left",e.pageX+2);
       $('#ghostbar').remove();
       $(document).unbind('mousemove');
       dragging = false;
   }
 });

Demo at http://jsfiddle.net/gaby/Bek9L/1779/

it is an alteration from the code i posted in Emulating frame-resize behavior with divs using jQuery without using jQuery UI?

Accordance answered 2/6, 2011 at 19:42 Comment(2)
+1 - Very nice solution. I just modified it a little because I needed a horizontal resize bar for one element to test fullscreen background images in different heights. Tough you could delete the unused elements $('#mousestatus').html("mousedown" + i++); and $('#clickevent').html('in another mouseUp event' + i++);Zebedee
@yves.. yes good point.. it was a left over from the original answer (to that other quiestion). updated linkAccordance
E
27

Been looking to do this, very nice solution by Gaby. Although my requirement was not to have any absolute elements and use percentages instead of pixels, so I've changed Gaby's code a little to cater for this (if anyone is interested)

CSS

#main{
  background-color: BurlyWood;
  float: right;
  height:200px;
  width: 75%;
}
#sidebar{
  background-color: IndianRed;
  width:25%;
  float: left;
  height:200px;
  overflow-y: hidden;
}
#dragbar{
  background-color:black;
  height:100%;
  float: right;
  width: 3px;
  cursor: col-resize;
}
#ghostbar{
  width:3px;
  background-color:#000;
  opacity:0.5;
  position:absolute;
  cursor: col-resize;
  z-index:999
}

JS

var i = 0;
var dragging = false;
$('#dragbar').mousedown(function(e){
   e.preventDefault();

   dragging = true;
   var main = $('#main');
   var ghostbar = $('<div>',
                    {id:'ghostbar',
                     css: {
                            height: main.outerHeight(),
                            top: main.offset().top,
                            left: main.offset().left
                           }
                    }).appendTo('body');

    $(document).mousemove(function(e){
      ghostbar.css("left",e.pageX+2);
   });

});

$(document).mouseup(function(e){
   if (dragging) 
   {
       var percentage = (e.pageX / window.innerWidth) * 100;
       var mainPercentage = 100-percentage;

       $('#console').text("side:" + percentage + " main:" + mainPercentage);

       $('#sidebar').css("width",percentage + "%");
       $('#main').css("width",mainPercentage + "%");
       $('#ghostbar').remove();
       $(document).unbind('mousemove');
       dragging = false;
   }
});

Demo: http://jsfiddle.net/Bek9L/3020/

Ecumenicism answered 1/10, 2015 at 9:22 Comment(0)
A
21

There is a much simpler way to achieve this. CSS 3 has a resize property to make an HTML element resizeable, while following other CSS properties like min/max widths etc.

.resizeable {
  resize: both;
  overflow: auto;
  border: 2px solid black;
}

For more info, here are the MDN Docs on the resize CSS 3 property.

Afterimage answered 23/5, 2020 at 18:17 Comment(1)
That is useful, but would be more helpful if you could make the whole side draggable. So, in the case of a navigation menu on the left of my screen, I might want to drag the right border of that to resize the space the menu has. This solution puts the resize control in the lower right corner, but I'm worried my users won't see it there at the bottom of the screen. (My div extends the full height of the window.)Prichard
C
17

Pure JS
Live Update
CSS Variable

let dragging = 0,
  body = document.body,
  target = document.getElementById('dragbar');

function clearJSEvents() {
  dragging = 0;
  body.removeEventListener("mousemove", resize);
  body.classList.remove('resizing');
}

function resize(e) {
  if (e.pageX > 400 || e.pageX < 200) {
    return;
  }
  body.style.setProperty("--left-width", e.pageX + 'px');
}

target.onmousedown = function(e) {
  e.preventDefault();
  dragging = 1;
  body.addEventListener('mousemove', resize);
  body.classList.add('resizing');
};

document.onmouseup = function() {
  dragging ? clearJSEvents() : '';
};
body {
  --left-width: 300px;
  padding: 0;
  margin: 0;
}

body.resizing {
  cursor: col-resize;
}

#main,
#sidebar,
#dragbar {
  top: 0;
  height: 100%;
  background: white;
  position: absolute;
}

#sidebar {
  background: #e6e9f0;
  width: var(--left-width);
}

#main {
  right: 0;
  overflow: scroll;
  width: calc(100% - var(--left-width));
}

#main section {
  margin: 20px auto;
  border-radius: 10px;
  background: white;
  height: 100px;
  width: calc(100% - 60px);
  transition: 0.3s ease-in-out 0s;
  box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
}

#main section:hover {
  box-shadow: 0px 3px 25px rgba(0, 0, 0, 0.2), 0px 0px 0px 1px #A8D1FD;
}

#dragbar {
  right: 0;
  width: 5px;
  opacity: 0;
  cursor: col-resize;
  background: #0099e5;
  transition: 0.3s ease-in-out 0s, opacity 0.3s ease-in-out 0s;
}

#dragbar:hover,
body.resizing #dragbar {
  opacity: 1;
  transition: 0.3s ease-in-out 0s, opacity 0.3s ease-in-out .3s;
}
<body>
  <section id="sidebar">
    <div id="dragbar"></div>
  </section>
  <main id="main">
    <section></section>
    <section></section>
    <section></section>
  </main>
</body>
Canasta answered 3/6, 2020 at 16:56 Comment(0)
B
9

Here's a slightly different way to do it without float but first with the content changing in real time dynamically ! (This is the best answer)

var dragging = false;

$('#dragbar').mousedown(function(e){
  e.preventDefault();
  dragging = true;
  var side = $('#side');
  $(document).mousemove(function(ex){
    side.css("width", ex.pageX +2);
  });
});

$(document).mouseup(function(e){
  if (dragging) 
  {
    $(document).unbind('mousemove');
    dragging = false;
  }
});
div{
    color: #fff;
    font-family: Tahoma, Verdana, Segoe, sans-serif;
    
}
#container{
    background-color:#2E4272;
    display:flex;
}
#side{
    background-color:#4F628E;
    width: 300px;
    position: relative;
}
#main{
    background-color:#7887AB;
    z-index: 1;
    flex-grow: 1;
}
#dragbar{
   background-color:black;
   height:100%;
   position: absolute;
   top: 0;
   right: 0;
   width: 5px;
   cursor: col-resize;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
    <div id="side">
      Side<br /> Blabla<br /> Blabla<br /> Blabla<br />
      <div id="dragbar"></div>
    </div>
    <div id="main">Dynamically sized content</div>
</div>
Blowhard answered 21/2, 2018 at 15:38 Comment(1)
The browser I support at my work is FF38 so enabling this using CSS grid was not possible. This is a great simple solution in my case.Elvera
D
6

Use jQuery UI with the ghost option:

See working jsFiddle demo:

$( "#resizable" ).resizable({ ghost: true });
Dasheen answered 2/6, 2011 at 19:4 Comment(2)
I don't want to ghost because my DIV has A LOT of elements in itSuccess
jsfiddle.net/BMwTy/3 has quite a few buttons and I don't see an issue with the ghosting option. How many elements are we talking here?Dasheen
R
3

I edited solution from the 1st comment but for vertical resizing of blocks

var i = 0;
var dragging = false;
   $('#dragbar').mousedown(function(e){
       e.preventDefault();
       
       dragging = true;
       var main = $('#main');
       var wrapper = $('#wrapper');
       var ghostbar = $('<div>',
                        {id:'ghostbar',
                         css: {
                                width: main.outerWidth(),
                           			top: e.pageY,
                                left: main.offset().left
                               }
                        }).appendTo('#wrapper');
       
        $(document).mousemove(function(e){
          ghostbar.css("top", (e.pageY + 2));
       });
       
    });

   $(document).mouseup(function(e){
       if (dragging) 
       {
           var percentage = ((e.pageY - $('#wrapper').offset().top) / $('#wrapper').height()) * 100;
           var mainPercentage = 100-percentage;  
           
           $('#sidebar').css("height",percentage + "%");
           $('#main').css("height",mainPercentage + "%");
           $('#ghostbar').remove();
           $(document).unbind('mousemove');
           dragging = false;
       }
    });
body,html{width:100%;height:100%;padding:0;margin:0;}
.clearfix:after {
    content: '';
    display: table;
    clear: both;
}
#wrapper {
  width: 600px;
  margin: 50px auto 0 auto;
  height: 300px;
  background: yellow;
}

#main{
   background-color: BurlyWood;
   height:40%;
    width: 100%;
    min-height: 30px;
   max-height: calc(100% - 30px);
}
#sidebar{
  display: flex;
  align-items: flex-end;
   background-color: IndianRed;
   width:100%;
   height:60%;
   overflow-y: hidden;
   min-height: 30px;
   max-height: calc(100% - 30px);
}

#dragbar{
   background-color:black;
   height:3px;
   float: right;
   width: 100%;
   cursor: row-resize;
}
#ghostbar{
  width: 100%;
    height: 3px;
    background-color:#000;
    opacity:0.5;
    position:absolute;
    cursor: col-resize;
    z-index:999}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div class="clearfix" id="wrapper">
  <div id="sidebar">
       <span id="position"></span>
      <div id="dragbar"></div>
  </div>
  <div id="main">  </div>
</div>

Demo: jsfiddle

Rearm answered 30/1, 2018 at 9:17 Comment(0)
S
1

You can find a resizable div here, which provides that feedback but only resizes once you release.

http://jqueryui.com/demos/resizable/#visual-feedback

Sommersommers answered 2/6, 2011 at 19:3 Comment(2)
This is ghosting the whole DIV. Mine has A LOT of elements, so I can't ghost the whole thing.Success
@Success - could you post an example of the kind of situation you're talking about? From a UX standpoint, ghosting the div is likely the more user-friendly solution especially if you're talking about resizing such a huge collection of elements (otherwise a user is resizing without any real feedback as to the result prior to releasing the mouse button). In any case, I'll just leave that as food for thought.Sommersommers
R
1

I wrote (most of) this a while back http://jsfiddle.net/ydTCZ/12/. It is for a table, but it would not be hard to adapt it to a div. I show you this because it provides insight into the jQuery required to create a resize effect, thus allowing for complete customization to suit your needs.

Rhizotomy answered 2/6, 2011 at 19:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.