当父可调整大小时,如何防止嵌套DIV的内容溢出父级?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当父可调整大小时,如何防止嵌套DIV的内容溢出父级?相关的知识,希望对你有一定的参考价值。

核心问题:我需要正确建立一个儿童<div>的高度,它嵌套在一个可调整大小的父母<div>。在调整父级的大小时,子级不应超出父级的范围。父本身应该受到限制,以免它缩小到超出孩子的最小可滚动范围。

DEAD ENDS:经过数小时的研究,我了解到即使使用calc()函数,CSS也无法动态设置<div>的高度和宽度。此外,似乎为了防止子<div>溢出其父级的维度,父级本身必须具有固定的大小。在后一种情况下,像height: auto; height: inherit;height: 100%;这样的样式都可能产生相同的结果。

之前已经在这里提出了类似的问题,但我找到的都没有解决调整大小问题。例如,提供给以下问题的解决方案无法正确解决我的问题。

Prevent child div from overflowing parent div

在我的情况下,我有一个<div>将用户调整大小和/或拖动到屏幕的任何部分。如有必要,<div>的内容应自动滚动。在任何情况下,它们都不应超过容器<div>的尺寸,即可调整尺寸的容器。我的情况要求我不使用jQuery,但欢迎使用javascript解决方案。 (即使PERL可能也值得,因为我将提供页面并通过来自Perl平台的AJAX进行更新。)

下面包含一个完整工作的示例,其中显示了子<div>如何超过其父级,即使启用了滚动,这也会发生,无论父级<div>如何调整大小。 (我在Firefox和Safari中测试过它。)

请注意,在我的实际应用程序中,<div>内容将通过<select>菜单中的每个用户选择通过AJAX提供,并且内容将具有不同的长度。无论返回的长度如何,容器/父级<div>应保持与用户自己的调整相同的大小。

<!DOCTYPE html>
<HTML lang="utf8">
<head>
<title>Example of Resizable/Draggable Container Div with Nested (Overflowing) Contents</title>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">

<style type="text/css">
.nested {
  background-color: #ffffcc;
  overflow-y: auto;
  overflow-x: hidden;
  max-height: 720px;
  height: inherit;
  color: #000;
  text-align: left;
  font-weight: normal;
  } 
.resizable {
  background: white;
  min-width: 100px;
  min-height: 120px;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 80px;
  left: 60px;
display: -webkit-box;   /* OLD - ios 6-, Safari 3.1-6, BB7 */
display: -ms-flexbox;  /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Safari 6.1+. iOS 7.1+, BB10 */
display: flex;         /* NEW, Spec - Firefox, Chrome, Opera */
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.resizable .resizers{
  width: 100%;
  height: 100%;
  border: 3px solid #4286f4;
  box-sizing: border-box;
}
.resizable .resizers .resizer{
  width: 3px;
  height: 5px;
  border-radius: 50%;  /*magic to turn square into circle*/
  background: black;
  border: 3px solid #4286f4;
  position: absolute;
  }
.resizable .resizers .resizer.top-left {
  left: -2px;
  top: -2px;
  cursor: nwse-resize; /*resizer cursor*/
}
.resizable .resizers .resizer.top-right {
  right: -2px;
  top: -2px;
  cursor: nesw-resize;
}
.resizable .resizers .resizer.bottom-left {
  left: -2px;
  bottom: -2px;
  cursor: nesw-resize;
}
.resizable .resizers .resizer.bottom-right {
  right: -2px;
  bottom: -2px;
  cursor: nwse-resize;
}  
#dragselection {
    position: absolute;
    top: 6px;
    left: 3%;
    z-index: 8;
    background-color: #f1f1f1;
    border: 1px solid #d3d3d3;
display: -webkit-box;   /* OLD - iOS 6-, Safari 3.1-6, BB7 */
display: -ms-flexbox;  /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Safari 6.1+. iOS 7.1+, BB10 */
display: flex;         /* NEW, Spec - Firefox, Chrome, Opera */
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.header {
    padding: 4px;
    margin-left: 2px;
    margin-right: 2px;
    margin-top: 4px;
    margin-bottom: 4px;
    text-align: center;
    cursor: move;
    z-index: 10;
    background-color: #2168a8;
    color: #fff;
    font-size: 14px;
    font-weight: bold;
    }
#CV1 {
    min-width:150px; 
    min-height:150px; 
    }    
.top-banner {
display: inline-block; 
margin-top: 0px; 
margin-right: 7px; 
margin-left: 5px; 
margin-bottom: 7px; 
background-color: #afb; 
border-radius: 12px; 
opacity: 0.9; 
box-shadow: 3px 3px #878087; 
max-width: 100%; 
height: auto;
align: auto;
text-align: center;
    }     
</style>


</head>
<body onload="dragElement('dragselection');">

<div class="top-banner">
<p style="margin-top: 30px; margin-right: 60px; margin-left: 60px; margin-bottom: 30px; text-align:center; font-size: 2.0em; color:#fff;text-shadow: 2px 1px 2px #050050;">&#9840; Easy Text Reference &#9840;</p>
</div>

<form id="myform" name="nmyform" method="POST" accept-charset="utf-8" action="URL_for_CGI" >
<article>

<h1>Example:</h1>

<div id="flex-box" name="nflex-box" class="flex-container">

<div class="container" id="mainscreen" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="header flex-container-head" id="header-box" name="nheader-box">  

       
<div class='resizable' id="dragselection" style="border: 1px solid gray; font-size:18px; height: 250px; ">
  <div class='resizers'>
    <div class='resizer top-left'></div>
    <div class='resizer top-right'></div>
    <div class='resizer bottom-left'></div>
    <div class='resizer bottom-right'></div>
    
    <div id="dragselectionheader" class='header'>
    Your Text Selection
 
  <select id="get_text" name="nget_text"  onchange="getAjaxResult(['selection_text','recordnum'], 'POST'); ">
<option value="">---- Selection Menu ----</option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
   
   </div>
    
  <div id="CV1" class="nested">
  A sample text:
  
  In the annals of human history, the growth of nations, the rise and fall of empires, appear as if dependent on the will and prowess of man; the shaping of events seems, to a great degree, to be determined by his power, ambition, or caprice. But in the word of God the curtain is drawn aside, and we behold, above, behind, and through all the play and counterplay of human interest and power and passions, the agencies of the All-merciful One, silently, patiently working out the counsels of His own will.  (Prophets and Kings, p. 499)
  </div>
  </div>
</div>


</div>
</div>

</div>

</article>

</form>


<script type="text/javascript">

/* Make the DIV element draggable: */
dragElement(document.getElementById(("dragselection")));

function dragElement(elmnt) {
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    /* if present, the header is where you move the DIV from: */
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  } else {
    /* otherwise, move the DIV from anywhere inside the DIV: */
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    /* get the mouse cursor position at startup: */
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    /* call a function whenever the cursor moves: */
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    /* calculate the new cursor position: */
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    /* set the element's new position: */
    if ((elmnt.offsetTop - pos2) < 0) { 
         elmnt.style.top = '0px'
    } else {     
         elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    }     
    if ((elmnt.offsetLeft - pos1) < 0) {
         elmnt.style.left = '0px'
    } else {
         elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    }
  }

  function closeDragElement() {
    /* stop moving when mouse button is released:*/
    document.onmouseup = null;
    document.onmousemove = null;    
  }
}

/* Modeled after: 
https://medium.com/the-z/making-a-resizable-div-in-js-is-not-easy-as-you-think-bda19a1bc53d 
*/

function makeResizableDiv(div) {
  const element = document.querySelector(div);
  const resizers = document.querySelectorAll(div + ' .resizer')
  const minimum_size = 120;
  var original_width = 0;
  var original_height = 0;
  var original_x = 0;
  var original_y = 0;
  var original_mouse_x = 0;
  var original_mouse_y = 0;

  for (var i = 0;i < resizers.length; i++) {
    const currentResizer = resizers[i];
    currentResizer.addEventListener('mousedown', function(e) {
      e.preventDefault()
      original_width = parseFloat(getComputedStyle(element, null).getPropertyValue('width').replace('px', ''));
      original_height = parseFloat(getComputedStyle(element, null).getPropertyValue('height').replace('px', ''));
      original_x = element.getBoundingClientRect().left;
      original_y = element.getBoundingClientRect().top;
      original_mouse_x = e.pageX;
      original_mouse_y = e.pageY;
      window.addEventListener('mousemove', resize)
      window.addEventListener('mouseup', stopResize)
    })
    
    function resize(e) {
      if (currentResizer.classList.contains('bottom-right')) {
        const width = original_width + (e.pageX - original_mouse_x);     
        const height = original_height + (e.pageY - original_mouse_y)     
        if (width > minimum_size) {
          element.style.width = width + 'px'     
          element.style.left = original_x + 'px' 
        }
        if (height > minimum_size) {
          element.style.height = height + 'px'     
          element.style.top = original_y + 'px' 
        }
      }
      else if (currentResizer.classList.contains('bottom-left')) {
        const height = original_height + (e.pageY - original_mouse_y)     
        const width = original_width - (e.pageX - original_mouse_x)     
        if (height > minimum_size) {
          element.style.height = height + 'px'     
          element.style.top = original_y+'px' 
        }
        if (width > minimum_size) {
          element.style.width = width + 'px'     
          element.style.left = original_x+(e.pageX-original_mouse_x)+'px' 
        }
      }
      else if (currentResizer.classList.contains('top-right')) {
        const width = original_width + (e.pageX - original_mouse_x)     
        const height = original_height - (e.pageY - original_mouse_y)     
        if (width > minimum_size) {
          element.style.width = width + 'px'     
          element.style.left = original_x + 'px'
        }
        if (height > minimum_size) {
          if (original_y+(e.pageY-original_mouse_y) < 0 ) {
            element.style.top = '0px'
          } else {
            element.style.height = height + 'px'     
            element.style.top = original_y+(e.pageY-original_mouse_y)+'px' 
          }
        }
      }
      else {          /* top-left */
        const width = original_width - (e.pageX - original_mouse_x)     
        const height = original_height - (e.pageY - original_mouse_y)     
        if (width > minimum_size) {
          element.style.width = width + 'px'     
          element.style.left = original_x+(e.pageX-original_mouse_x)+'px' 
        }
        if (height > minimum_size) {
         if (original_y+(e.pageY-original_mouse_y) < 0 ) {
            element.style.top = '0px'
          } else {
            element.style.height = height + 'px'     
            element.style.top = original_y+(e.pageY-original_mouse_y)+'px' 
          }
        }
      }
    }
    
    function stopResize() {
      window.removeEventListener('mousemove', resize)
    }
  }
}
makeResizableDiv('.resizable')

</script>
</body>
</html>

更新:我已经调整了上面的代码,以反映到目前为止提供的建议。不幸的是,使用此配置,我无法限制父级的宽度。然后,孩子继承任何小于100%(或自动)的东西,结果不利。但是,我不希望父母占据屏幕的整个宽度,所以这个解决方案是不够的。

我现在已经找到了可能与Firefox一起使用的解决方法。我的Safari似乎不接受flex选项,因此仍然没有跨浏览器解决方案。对于Firefox,以下JavaScript代码可以在页面加载后设置<div>位置,如下所示:

document.getElementById('dragselection').setAttribute("style","width:320px; height:240px; font-size:18px;");

我现在已经了解到以下代码更兼容跨浏览器,并使Safari正确呈现它。

display: -webkit-box;   /* OLD - iOS 6-, Safari 3.1-6, BB7 */
display: -ms-flexbox;  /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Safari 6.1+. iOS 7.1+, BB10 */
display: flex;         /* NEW, Spec - Firefox, Chrome, Opera */
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;

我已在示例脚本中的两个位置更新了该代码。这可能是可行的。

答案

你可以在这里使用flexbox css。父DIV将弯曲,flex-direction:列。

并且对于最小可拖动屏幕,父级高度为120px,而子级最小高度为150px,从#CV1中删除样式。

你能更新这些样式并检查吗?

.resizable .resizers{
  width: 100%;
  height: 100%;
  border: 3px solid #4286f4;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
}

.nested {
  background-color: #ffffcc;
  overflow-y: auto;
  overflow-x: hidden;
  max-height: 720px;
  height: inherit;
  color: #000;
  text-align: left;
  font-weight: normal;
  }

以上是关于当父可调整大小时,如何防止嵌套DIV的内容溢出父级?的主要内容,如果未能解决你的问题,请参考以下文章

外部 jquery 可拖动/可调整大小的 div 不允许我选择内部跨度的文本

Jquery 可调整大小的问题,其中 div 合同的宽度和高度为零

Jquery UI 可排序和可调整大小的 Div

如何创建多个受容器 div 约束的可调整大小的同级 div 元素

jQuery UI 可调整大小:单独使用东手柄时的自动高度

在可拖动和可调整大小的 Jquery div 中删除