admin管理员组

文章数量:1194611

I am trying to create a layout which allows you to resize the sidebar by dragging one edge of it. This behavior can be seen in CodePen/CodeSandbox, etc.. - you can drag each 'code window' to resize it. I am looking for this same behavior but with the page layout.

What I have come up with allows me to drag to resize, but if there is a lot of content within the 'main' area (area that is not the sidebar) it throws off the drag.

I want to be able to drag all the way to the edge of the screen, regardless of the content within.

I think the best way to show this issue is by a demo:

Original Demo:

const resizer = document.querySelector("#resizer");
const sidebar = document.querySelector("#sidebar");

resizer.addEventListener("mousedown", (event) => {
  document.addEventListener("mousemove", resize, false);
  document.addEventListener("mouseup", () => {
    document.removeEventListener("mousemove", resize, false);
  }, false);
});

function resize(e) {
  const size = `${e.x}px`;
  sidebar.style.width = size;
}

/** 
 * Helpers 
 */

sidebar.style.width = '325px';
const mainContent = document.querySelector("#main-content");

function addContent() {
  const mainContentStr = [...Array(10).keys()].map(i => "Main Content");
  mainContent.innerHTML += mainContentStr.join(' ') + '<br /><br /><h1>Now drag to see how difficult it is, remove content to see how easy it is</h1>';
}

function removeContent() {
  mainContent.innerHTML = '';
}

document.querySelector("#add-content")
  .addEventListener('click', () => addContent())

document.querySelector("#remove-content")
  .addEventListener('click', () => removeContent())
body {
  position: relative;
  height: auto;
  min-height: 100vh;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  overflow: hidden;
  margin: 0;
}

#wrapper {
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  flex-direction: column;
  overflow: hidden;
  position: absolute;
  height: 100%;
  width: 100%;
  display: flex;
  margin: 0;
  padding: 0;
}

#container {
  width: 100%;
  height: 100%;
  flex-shrink: 0;
  position: relative;
  display: flex;
  overflow: hidden;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#sidebar {
  height: 100%;
  position: relative;
  margin 0;
  padding: 0;
  box-sizing: border-box;
  background: lightgray;
  border: 2px solid darkgray;
}

#resizer {
  position: relative;
  z-index: 2;
  width: 18px;
  cursor: col-resize;
  border-left: 1px solid rgba(255, 255, 255, 0.05);
  border-right: 1px solid rgba(0, 0, 0, 0.4);
  background: #333642;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#main {
  background: lightblue;
  height: 100%;
  flex-grow: 1;
  flex-direction: row;
  position: relative;
  display: flex;
  margin: 0;
  padding: 0;
}

#add-content {
  width: 80px;
  float: right;
  background-color: forestgreen;
}

#remove-content {
  width: 80px;
  float: right;
  background-color: salmon;
}
<div id="wrapper">
  <div id="container">
    <div id="sidebar">
      <p>Sidebar content</p>
      <button id="add-content">Add Content</button>
      <button id="remove-content">Remove Content</button>
    </div>
    <div id="resizer"></div>
    <div id="main">
      <p id="main-content"></p>
    </div>
  </div>
</div>

I am trying to create a layout which allows you to resize the sidebar by dragging one edge of it. This behavior can be seen in CodePen/CodeSandbox, etc.. - you can drag each 'code window' to resize it. I am looking for this same behavior but with the page layout.

What I have come up with allows me to drag to resize, but if there is a lot of content within the 'main' area (area that is not the sidebar) it throws off the drag.

I want to be able to drag all the way to the edge of the screen, regardless of the content within.

I think the best way to show this issue is by a demo:

Original Demo:

const resizer = document.querySelector("#resizer");
const sidebar = document.querySelector("#sidebar");

resizer.addEventListener("mousedown", (event) => {
  document.addEventListener("mousemove", resize, false);
  document.addEventListener("mouseup", () => {
    document.removeEventListener("mousemove", resize, false);
  }, false);
});

function resize(e) {
  const size = `${e.x}px`;
  sidebar.style.width = size;
}

/** 
 * Helpers 
 */

sidebar.style.width = '325px';
const mainContent = document.querySelector("#main-content");

function addContent() {
  const mainContentStr = [...Array(10).keys()].map(i => "Main Content");
  mainContent.innerHTML += mainContentStr.join(' ') + '<br /><br /><h1>Now drag to see how difficult it is, remove content to see how easy it is</h1>';
}

function removeContent() {
  mainContent.innerHTML = '';
}

document.querySelector("#add-content")
  .addEventListener('click', () => addContent())

document.querySelector("#remove-content")
  .addEventListener('click', () => removeContent())
body {
  position: relative;
  height: auto;
  min-height: 100vh;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  overflow: hidden;
  margin: 0;
}

#wrapper {
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  flex-direction: column;
  overflow: hidden;
  position: absolute;
  height: 100%;
  width: 100%;
  display: flex;
  margin: 0;
  padding: 0;
}

#container {
  width: 100%;
  height: 100%;
  flex-shrink: 0;
  position: relative;
  display: flex;
  overflow: hidden;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#sidebar {
  height: 100%;
  position: relative;
  margin 0;
  padding: 0;
  box-sizing: border-box;
  background: lightgray;
  border: 2px solid darkgray;
}

#resizer {
  position: relative;
  z-index: 2;
  width: 18px;
  cursor: col-resize;
  border-left: 1px solid rgba(255, 255, 255, 0.05);
  border-right: 1px solid rgba(0, 0, 0, 0.4);
  background: #333642;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#main {
  background: lightblue;
  height: 100%;
  flex-grow: 1;
  flex-direction: row;
  position: relative;
  display: flex;
  margin: 0;
  padding: 0;
}

#add-content {
  width: 80px;
  float: right;
  background-color: forestgreen;
}

#remove-content {
  width: 80px;
  float: right;
  background-color: salmon;
}
<div id="wrapper">
  <div id="container">
    <div id="sidebar">
      <p>Sidebar content</p>
      <button id="add-content">Add Content</button>
      <button id="remove-content">Remove Content</button>
    </div>
    <div id="resizer"></div>
    <div id="main">
      <p id="main-content"></p>
    </div>
  </div>
</div>


Updated Demo:

After adding buttons, they appear stretched vertically 100%

const resizer = document.querySelector("#resizer");
const sidebar = document.querySelector("#sidebar");

resizer.addEventListener("mousedown", (event) => {
  document.addEventListener("mousemove", resize, false);
  document.addEventListener("mouseup", () => {
    document.removeEventListener("mousemove", resize, false);
  }, false);
});

function resize(e) {
  const size = `${e.x}px`;
  sidebar.style.flexBasis = size;
}

/** 
 * Helpers 
 */

sidebar.style.flexBasis = '325px';
const mainContent = document.querySelector("#main-content");

function addContent() {
  const mainContentStr = [...Array(10).keys()].map(i => "Main Content");
  mainContent.innerHTML += mainContentStr.join(' ') + '<br /><br /><h1>Now drag to see how difficult it is, remove content to see how easy it is</h1>';
}

function removeContent() {
  mainContent.innerHTML = '';
}

document.querySelector("#add-content")
  .addEventListener('click', () => addContent())

document.querySelector("#remove-content")
  .addEventListener('click', () => removeContent())
body {
  position: relative;
  height: auto;
  min-height: 100vh;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  overflow: hidden;
  margin: 0;
}

#wrapper {
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  flex-direction: column;
  overflow: hidden;
  position: absolute;
  height: 100%;
  width: 100%;
  display: flex;
  margin: 0;
  padding: 0;
}

#container {
  width: 100%;
  height: 100%;
  flex-shrink: 0;
  position: relative;
  display: flex;
  overflow: hidden;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#sidebar {
  height: 100%;
  position: relative;
  margin 0;
  padding: 0;
  box-sizing: border-box;
  background: lightgray;
  border: 2px solid darkgray;
  
  min-width: 0;
}

#resizer {
  flex-basis: 18px;

  position: relative;
  z-index: 2;
  cursor: col-resize;
  border-left: 1px solid rgba(255, 255, 255, 0.05);
  border-right: 1px solid rgba(0, 0, 0, 0.4);
  background: #333642;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#main {
  flex-basis: 0;
  flex-grow: 1;
  min-width: 0;

  background: lightblue;
  height: 100%;
  flex-direction: row;
  position: relative;
  display: flex;
  margin: 0;
  padding: 0;
}

#add-content {
  width: 80px;
  float: right;
  background-color: forestgreen;
}

#remove-content {
  width: 80px;
  float: right;
  background-color: salmon;
}
<div id="wrapper">
  <div id="container">
    <div id="sidebar">
      <p>Sidebar content</p>
    </div>
    <div id="resizer"></div>
    <div id="main">
      <button id="add-content">Add Content</button>
      <button id="remove-content">Remove Content</button>
      <p id="main-content"></p>
    </div>
  </div>
</div>

Share Improve this question edited Apr 2, 2020 at 5:58 Matt Oestreich asked Apr 1, 2020 at 23:14 Matt OestreichMatt Oestreich 8,5283 gold badges18 silver badges45 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 28

To set a fixed invariable width in Flexbox, use flex-basis instead of width. From that fixed size, a flex item can then shrink or grow depending on the available space and the properties of flex-grow and flex-shrink.

Furthermore, the default min-width value of a flex item is auto. This means that the item cannot have a width smaller than its content size, even when you set its flex-basis to 0px. This means that we have to override the default min-width value to 0px so that upon dragging the #resizer element, it can shrink itself completely.

Here's a working example. I merely tweaked your width property to flex-basis in both JS and CSS. And then, I also added a min-width property of 0px to both #main and #sidebar.

const resizer = document.querySelector("#resizer");
const sidebar = document.querySelector("#sidebar");

resizer.addEventListener("mousedown", (event) => {
  document.addEventListener("mousemove", resize, false);
  document.addEventListener("mouseup", () => {
    document.removeEventListener("mousemove", resize, false);
  }, false);
});

function resize(e) {
  const size = `${e.x}px`;
  sidebar.style.flexBasis = size;
}

/** 
 * Helpers 
 */

sidebar.style.flexBasis = '325px';
const mainContent = document.querySelector("#main-content");

function addContent() {
  const mainContentStr = [...Array(10).keys()].map(i => "Main Content");
  mainContent.innerHTML += mainContentStr.join(' ') + '<br /><br /><h1>Now drag to see how difficult it is, remove content to see how easy it is</h1>';
}

function removeContent() {
  mainContent.innerHTML = '';
}

document.querySelector("#add-content")
  .addEventListener('click', () => addContent())

document.querySelector("#remove-content")
  .addEventListener('click', () => removeContent())
body {
  position: relative;
  height: auto;
  min-height: 100vh;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  overflow: hidden;
  margin: 0;
}

#wrapper {
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  flex-direction: column;
  overflow: hidden;
  position: absolute;
  height: 100%;
  width: 100%;
  display: flex;
  margin: 0;
  padding: 0;
}

#container {
  width: 100%;
  height: 100%;
  flex-shrink: 0;
  position: relative;
  display: flex;
  overflow: hidden;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#sidebar {
  height: 100%;
  position: relative;
  margin 0;
  padding: 0;
  box-sizing: border-box;
  background: lightgray;
  border: 2px solid darkgray;
  
  min-width: 0;
}

#resizer {
  flex-basis: 18px;

  position: relative;
  z-index: 2;
  cursor: col-resize;
  border-left: 1px solid rgba(255, 255, 255, 0.05);
  border-right: 1px solid rgba(0, 0, 0, 0.4);
  background: #333642;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#main {
  flex-basis: 0;
  flex-grow: 1;
  min-width: 0;

  background: lightblue;
  height: 100%;
  flex-direction: row;
  position: relative;
  display: flex;
  margin: 0;
  padding: 0;
}

#add-content {
  width: 80px;
  float: right;
  background-color: forestgreen;
}

#remove-content {
  width: 80px;
  float: right;
  background-color: salmon;
}
<div id="wrapper">
  <div id="container">
    <div id="sidebar">
      <p>Sidebar content</p>
      <button id="add-content">Add Content</button>
      <button id="remove-content">Remove Content</button>
    </div>
    <div id="resizer"></div>
    <div id="main">
      <p id="main-content"></p>
    </div>
  </div>
</div>

本文标签: javascriptResizable SidebarDrag To ResizeStack Overflow