admin管理员组

文章数量:1291448

I want to make a vertically draggable division of two areas like the following.

I just want to modify a online example of draggable divs to be what I want. Finally, I got this. Can someone give me some hints to modify it?


JSFiddle Link : /


HTML

<div class="container">
  <div class="area1">
Area 1
  </div>
  <div class="drag">

  </div>
  <div class="area2">
Area 2
  </div>
</div>

CSS

.container {
  position: fixed;
  top: 51px;
  right: 0px;
  bottom: 0px;
  left: 0px;
  background-color: #272822;
  border: 1px solid #222;
 // margin: 0 auto;
  //display: inline-block;
}

.area1 {
  position: absolute;
  height: 100%;
  width: 30%;
  background-color: #ddd;
  display: inline-block;
}

.drag {
  position: fixed;

  width: 5px;
  height: 100%;
  background-color: #444;
  display: inline-block;
}

.area2 {
  position: absolute;
  right: 0;
  height: 100%;
  width: 30%;
  background-color: #ddd;
  display: inline-block;
}

JavaScript

$(document).ready(function() {

  $('.drag').on('mousedown', function(e) {
    var $area1 = $('.area1'),
        $area2 = $('.area2'),
        startWidth_a1 = $area1.width(),
        startWidth_a2 = $area2.width(),
        pX = e.pageX;

    $(document).on('mouseup', function(e) {
      $(document).off('mouseup').off('mousemove');
    });

    $(document).on('mousemove', function(me) {
      var mx = (me.pageX - pX);
      $area1.css({
        width: startWidth_a1 - mx;
      });
      $area2.css({
        //left: mx / 2,
        width: startWidth_a2 - mx,
        //top: my
      });
    });

  });
});

I want to make a vertically draggable division of two areas like the following.

I just want to modify a online example of draggable divs to be what I want. Finally, I got this. Can someone give me some hints to modify it?


JSFiddle Link : https://jsfiddle/casperhongkong/omekvtka/14/


HTML

<div class="container">
  <div class="area1">
Area 1
  </div>
  <div class="drag">

  </div>
  <div class="area2">
Area 2
  </div>
</div>

CSS

.container {
  position: fixed;
  top: 51px;
  right: 0px;
  bottom: 0px;
  left: 0px;
  background-color: #272822;
  border: 1px solid #222;
 // margin: 0 auto;
  //display: inline-block;
}

.area1 {
  position: absolute;
  height: 100%;
  width: 30%;
  background-color: #ddd;
  display: inline-block;
}

.drag {
  position: fixed;

  width: 5px;
  height: 100%;
  background-color: #444;
  display: inline-block;
}

.area2 {
  position: absolute;
  right: 0;
  height: 100%;
  width: 30%;
  background-color: #ddd;
  display: inline-block;
}

JavaScript

$(document).ready(function() {

  $('.drag').on('mousedown', function(e) {
    var $area1 = $('.area1'),
        $area2 = $('.area2'),
        startWidth_a1 = $area1.width(),
        startWidth_a2 = $area2.width(),
        pX = e.pageX;

    $(document).on('mouseup', function(e) {
      $(document).off('mouseup').off('mousemove');
    });

    $(document).on('mousemove', function(me) {
      var mx = (me.pageX - pX);
      $area1.css({
        width: startWidth_a1 - mx;
      });
      $area2.css({
        //left: mx / 2,
        width: startWidth_a2 - mx,
        //top: my
      });
    });

  });
});
Share Improve this question edited Feb 3, 2016 at 17:01 Joshua LI asked Dec 26, 2015 at 15:31 Joshua LIJoshua LI 4,76311 gold badges44 silver badges75 bronze badges 2
  • 6 I heavily remend split.js for this nathancahill.github.io/Split.js – Donnie D'Amato Commented Dec 27, 2015 at 14:38
  • 2 link to split.js is dead. Now it's split.js – Danil Pyatnitsev Commented Feb 7, 2019 at 13:36
Add a ment  | 

2 Answers 2

Reset to default 5

For javascript, I would remend checking out a library, as this is slitghtly more plicated than just a few lines. @fauxserious gave Split.js as a fantastic example.

This is possible in pure HTML/CSS, though slightly limited, as discussed here.

HTML:

<div class="split-view">
    <div class="resize-x panel" style="width: 216px;">
      Panel A
    </div>
    <div class="panel">
      Panel B
    </div>
</div>

CSS:

/* Panels: */
.panel{ 
    padding: 1em; 
    border-width: 6px; 
    border-style: solid; 
    height: 4em; 
}

/* Resizing */
.resize-x { 
    resize: horizontal;
    overflow: auto;
}

/* Split View */
.split-view {
    margin: 1em 0; 
    width: 100%;
    clear: both;
    display: table;
}

.split-view .panel {
    display: table-cell;
}

Based on @afischer's table-cell solution, here is an alternative one.
I have had to put accordions within the left side panel.

The sticky headers of the accordions require overflow to be visible,
while resize requires overflow to be anything but visible:
https://caniuse./#feat=css-sticky.

In the same time, I didn't need anything to place into the right side panel.

Thus, an overe was employing resize on the right panel, and rotating by 180 deg to get the dragable side to the middle, as well as this way the dragable corner relocated to the top (visible without scrolling).

Plus some highlight has been added to the dragable corner.

/* Panels: */
.panel{ 
  padding: 1em; 
  border-width: 6px; 
  border-style: solid; 
  height: 4em; 
}

/* Resizing */
.resize-x { 
  resize: horizontal;
  overflow: auto;
  transform: rotate(180deg);
  border-right: solid gray 1px;
}

/* Split View */
.split-view {
  margin: 1em 0; 
  width: 100%;
  clear: both;
  display: table;
}

.split-view .panel {
  display: table-cell;
}

.resize-x::-webkit-resizer {
    border-width: 8px;
    border-style: solid;
    border-color: transparent orangered orangered transparent;
  }
<div class="split-view">
    <div
      class="panel"
      style="width: 216px;">
        Panel A
    </div>
    <div class="panel resize-x">
      Panel B
    </div>
</div>

Unfortunately there are two disappointing thing with the above:

  • Firefox cannot handle the bination of table-cell and resize
  • Only a corner of the grabber is responsive, which can even be scrolled out easily

Here is an other solution which also takes the above two problems into account

  • without resize CSS property
  • and with full height responsive grabber

It's a bination of a flexbox and an input:range slider.

The trick is that the pointer-event CSS property can be different

  • on the slider's background
  • and on its grabber.

The slider covers the entire view. The background of the slider is transparent for the events too (pointer-events: none), while the dragbar itself catches the events (pointer-events: auto).

It requires minor Javascript and because I've implemented the production version in Nuxt.js, I use Vue.js here, instead of vanilla JS.

new Vue({
        el: '#vue',

        data: {
          windowWidth: null,
          splitWidth: null,
        },

        mounted() {
          this.windowWidth = window.innerWidth;
          // For arbitrary initial position:
          this.splitWidth = this.windowWidth * 2/3;
        },

        puted: {
          flexRatio() {
            return this.splitWidth / this.windowWidth;
          }
        }

      })
body {
        margin:0;
      }

      main {
        display: flex;
        width: 100%;
        height: 100vh;
      }

      article {
        display: flex;
      }

      section {
        width: 100%;
        height: 100%;
        text-align: justify;
        padding: 20px;
      }

      .section-left {
        background-color: darkseagreen;
      }

      .section-right {
        background-color: orangered;
      }

      #split-grabber {
        pointer-events: none;
        position: fixed;
        top: 0; right: 0; bottom: 0; left: 0;
        -webkit-appearance: none;
      /* Safari allows dragging behind scroll bar.
        We fix it by shrinking its width on the right side via both
        its range value      :max="windowWidth - 12"
        and its width (CSS)   width: calc(100% - 12px)
        ...synchronously  */
        width: calc(100% - 12px);
        height: 100vh;
        background: transparent;
        outline: none;
        margin: 0;
      }

      #split-grabber::-webkit-slider-thumb {
        z-index: 1;
        pointer-events: auto;
        -webkit-appearance: none;
        appearance: none;
        width: 5px;
        height: 100vh;
        background: lightgray;
        box-shadow: 1px 2px 2px 0px gray;
        cursor: col-resize;
      }

      #split-grabber::-moz-range-thumb {
        z-index: 1;
        pointer-events: auto;
        -webkit-appearance: none;
        appearance: none;
        width: 5px;
        height: 100vh;
        background: lightgray;
        box-shadow: 1px 2px 2px 0px gray;
        cursor: col-resize;
      }
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.5.17/vue.js"></script>

<main id="vue">
      <!-- Safari allows dragging behind scroll bar
      We fix it by shrinking its width on the right side via both
      its range value      :max="windowWidth - 12"
      and its width (CSS)   width: calc(100% - 12px)
      ...synchronously  -->
      <input
        id="split-grabber"
        type="range" 
        v-model="splitWidth"
        :max="windowWidth - 12"
      >
      <article
      class="article"
      :style="{'flex': flexRatio}"
      >
        <section
        class="section section-left">
          splitWidth:{{ splitWidth }}px<br>
          “There was a rich man who always dressed in the finest clothes and lived in luxury every day.
          And a very poor man named Lazarus, whose body was covered with sores, was laid at the rich man’s gate.
          He wanted to eat only the small pieces of food that fell from the rich man’s table. And the dogs would e and lick his sores.
          Later, Lazarus died, and the angels carried him to the arms of Abraham. The rich man died, too, and was buried.
          In the place of the dead, he was in much pain. The rich man saw Abraham far away with Lazarus at his side.
          He called, ‘Father Abraham, have mercy on me! Send Lazarus to dip his finger in water and cool my tongue, because I am suffering in this fire!’
        </section>  
      </article>
      <article
        class="article"
        :style="{'flex': 1-flexRatio}"  
      >
        <section class="section section-right">
          But Abraham said, ‘Child, remember when you were alive you had the good things in life, but bad things happened to Lazarus. Now he is forted here, and you are suffering.
          Besides, there is a big pit between you and us, so no one can cross over to you, and no one can leave there and e here.’
          The rich man said, ‘Father, then please send Lazarus to my father’s house.
          I have five brothers, and Lazarus could warn them so that they will not e to this place of pain.’
          But Abraham said, ‘They have the law of Moses and the writings of the prophets; let them learn from them.’
          The rich man said, ‘No, father Abraham! If someone goes to them from the dead, they would believe and change their hearts and lives.’
          But Abraham said to him, ‘If they will not listen to Moses and the prophets, they will not listen to someone who es back from the dead.’”        
        </section>
      </article>
    </main>

本文标签: javascriptVertically Draggable Division of Two AreasStack Overflow