Home > Enterprise >  HTML - Resize multiple divs and their content
HTML - Resize multiple divs and their content

Time:08-18

I am looking to create a bottom pannel with a resizable height. The top pannel consists of 2 divs with a resizable width. I was able to follow this https://htmldom.dev/create-resizable-split-views/ , but the vertical resizing is not resizing the contents of the two top divs. How can I fill the contents of the top container with the contents of the two Divs, to ensure that they resize when the bottom pannel is dragged up?

In other words, I'm looking for two top horizontally resizable pannels and one bottom pannel vertically resizable from them, while shrinking/expanding the contents during resize.

Edit: The bottom container needs to be set on all tabs and show up under all tab content on the page.

<div >
  <div class = "container__top">
      <div  >
          <body >
              <div >
                  <div >
                      <div >
                          <div >
                              <div >
                                      <div >
                                               STUFF</div>
                                       <div  data-direction="horizontal"></div>
                                      <div >
                                               STUFF</div> 
                              </div>
                        </div>
                    </div>
                </div>
             <div ></div>
         </body>
       </div>
   </div>
       <div  data-direction="vertical"></div>
     <div class = "container__bottom">
      STUFF</div>

CodePudding user response:

You could try something like this. You'll have to be explicit for a few things, like parent height and the min/max heights for top and bottom sections, but this could be a decent start. It's ugly, sorry.

edit: it's still ugly, and you'll have to fix up the tab/hide function for more tabs, but this works as intended as far as I can tell.

document.addEventListener('DOMContentLoaded', function() {
  const resizable = function(resizer) {
    const direction = resizer.getAttribute('data-direction') || 'horizontal';
    const prevSibling = resizer.previousElementSibling;
    const nextSibling = resizer.nextElementSibling;

    // The current position of mouse
    let x = 0;
    let y = 0;
    let prevSiblingHeight = 0;
    let prevSiblingWidth = 0;

    // Handle the mousedown event
    // that's triggered when user drags the resizer
    const mouseDownHandler = function(e) {
      // Get the current mouse position
      x = e.clientX;
      y = e.clientY;
      const rect = prevSibling.getBoundingClientRect();
      prevSiblingHeight = rect.height;

      // Attach the listeners to `document`
      document.addEventListener('mousemove', mouseMoveHandler);
      document.addEventListener('mouseup', mouseUpHandler);
    };

    const mouseMoveHandler = function(e) {
      // How far the mouse has been moved
      const dx = e.clientX - x;
      const dy = e.clientY - y;
      const parentHeight = resizer.parentNode.getBoundingClientRect().height;

      const h = (prevSiblingHeight   dy)
      prevSibling.style.height = `${h}px`;
      nextSibling.style.height = `${parentHeight - h}px`;

      const cursor = 'row-resize';
      resizer.style.cursor = cursor;
      document.body.style.cursor = cursor;

      prevSibling.style.userSelect = 'none';
      prevSibling.style.pointerEvents = 'none';

      nextSibling.style.userSelect = 'none';
      nextSibling.style.pointerEvents = 'none';
    };

    const mouseUpHandler = function() {
      resizer.style.removeProperty('cursor');
      document.body.style.removeProperty('cursor');

      prevSibling.style.removeProperty('user-select');
      prevSibling.style.removeProperty('pointer-events');

      nextSibling.style.removeProperty('user-select');
      nextSibling.style.removeProperty('pointer-events');

      // Remove the handlers of `mousemove` and `mouseup`
      document.removeEventListener('mousemove', mouseMoveHandler);
      document.removeEventListener('mouseup', mouseUpHandler);
    };

    // Attach the handler
    resizer.addEventListener('mousedown', mouseDownHandler);
  };

  // Query all resizers
  document.querySelectorAll('.resizer').forEach(function(ele) {
    resizable(ele);
  });

  // Query the element
  const horizontalResizer = document.getElementById('dragMeHorizontal');
  const leftSide = horizontalResizer.previousElementSibling;
  const rightSide = horizontalResizer.nextElementSibling;

  // The current position of mouse
  let x = 0;
  let y = 0;
  let leftWidth = 0;

  // Handle the mousedown event
  // that's triggered when user drags the resizer
  const mouseDownHandler = function(e) {
    // Get the current mouse position
    x = e.clientX;
    y = e.clientY;
    leftWidth = leftSide.getBoundingClientRect().width;

    // Attach the listeners to `document`
    document.addEventListener('mousemove', mouseMoveHandler);
    document.addEventListener('mouseup', mouseUpHandler);
  };

  const mouseMoveHandler = function(e) {
    // How far the mouse has been moved
    const dx = e.clientX - x;
    const dy = e.clientY - y;

    const newLeftWidth = ((leftWidth   dx) * 100) / horizontalResizer.parentNode.getBoundingClientRect().width;
    leftSide.style.width = `${newLeftWidth}%`;

    horizontalResizer.style.cursor = 'col-resize';
    document.body.style.cursor = 'col-resize';

    leftSide.style.userSelect = 'none';
    leftSide.style.pointerEvents = 'none';

    rightSide.style.userSelect = 'none';
    rightSide.style.pointerEvents = 'none';
  };

  const mouseUpHandler = function() {
    horizontalResizer.style.removeProperty('cursor');
    document.body.style.removeProperty('cursor');

    leftSide.style.removeProperty('user-select');
    leftSide.style.removeProperty('pointer-events');

    rightSide.style.removeProperty('user-select');
    rightSide.style.removeProperty('pointer-events');

    // Remove the handlers of `mousemove` and `mouseup`
    document.removeEventListener('mousemove', mouseMoveHandler);
    document.removeEventListener('mouseup', mouseUpHandler);
  };

  // Attach the handler
  horizontalResizer.addEventListener('mousedown', mouseDownHandler);
});

// Tab Changer
function changeActiveTab(tabNumber) {
  const allOtherTabs = document.getElementsByClassName("tab")
  const hideElements = [...allOtherTabs].filter((element, index) => index !== tabNumber)
  const selectedTab = document.getElementsByClassName("tab")[tabNumber]
  hideElements.forEach(element => element.classList.add("hidden"));
  selectedTab.classList.remove("hidden");
}
// handle tab 1 select
document.getElementById("tab1").addEventListener('mousedown', () => {
  changeActiveTab(0)
})
// handle tab 2 select
document.getElementById("tab2").addEventListener('mousedown', () => {
  changeActiveTab(1)
})
// handle tab 3 select
document.getElementById("tab3").addEventListener('mousedown', () => {
  changeActiveTab(2)
})
.resizer[data-direction='vertical'] {
  background-color: #cbd5e0;
  cursor: ns-resize;
  height: 10px;
  width: 100%;
}

.button__container {
  margin: 6px 12px;
  display: flex;
  flex-direction: row;
}

.tab__internal {
  max-height: 18%;
}

button {
  background-color: orange;
  border: none;
  padding: 8px;
  min-width: 150px;
  margin: 1px;
  border: 1px solid teal;
}

.main__container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  border: 1px solid blue;
}

.sub__container {
  height: 250px;
  /* Misc */
}

#tab__2 {
  background-color: green;
}

#tab__3 {
  background-color: teal;
}

.container__top {
  /* Initial height */
  height: 100%;
  /* Misc */
  display: flex;
  flex-direction: row;
  background-color: green;
}

.hidden {
  display: none;
}

.tabs__container {
  background-color: blue;
  height: 100px;
  max-height: calc(100% - 100px);
  min-height: 50px;
}

.tab__contents {
  height: 100%;
}

.container__bottom {
  /* Take the remaining height */
  width: 100%;
  height: 150px;
  min-height: 100px;
  max-height: calc(100% - 50px);
  /* Misc */
  display: flex;
  flex-direction: column;
  background-color: red;
}

.container__left {
  width: 50%;
  height: 100%;
  /* Misc */
  display: flex;
  background-color: goldenrod;
}

.resizer__horizontal {
  background-color: #cbd5e0;
  cursor: ew-resize;
  height: 100%;
  width: 5px;
}

.container__right {
  /* Take the remaining width */
  flex: 1;
  height: 100%;
  /* Misc */
  display: flex;
  background-color: purple;
}
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>HTML DOM - Create resizable split views</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="stylesheet" href="/css/demo.css" />
  <link rel="preconnect" href="https://fonts.gstatic.com" />
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter&family=Source Code Pro&display=swap" />

</head>

<body>
  <div >
    <h3>Main Container</h3>
    <div >
      <button  id="tab1">Tab 1</button>
      <button  id="tab2">Tab 2</button>
      <button  id="tab3">Tab 3</button>
    </div>
  </div>
  <div >
    <div >

      <div  id="tab__1">
        <div >
          <div >
            <div >stuff</div>
            <div >stuff</div>
            <div >stuff</div>
            <div >stuff</div>
          </div>
        </div>
        <div  id="dragMeHorizontal"></div>
        <div >Right</div>
      </div>

      <div  id="tab__2">
        <div >Tab 2</div>
      </div>

      <div  id="tab__3">
        <div >Tab </div>
      </div>

    </div>
    <div  data-direction="vertical"></div>
    <div >
      <h4>Bottom</h4>
      <p>Stuff up in here.</p>
    </div>
  </div>
</body>

</html>

  • Related