【问题标题】:Can I change the design of the textarea resize handle in CSS?我可以更改 CSS 中 textarea 调整大小手柄的设计吗?
【发布时间】:2016-04-20 13:10:32
【问题描述】:

通常,textarea 可以通过拖动右下角的小三角形手柄来双向调整大小。一旦我通过设置textarea { resize: vertical; } 禁用水平调整大小,textarea 只能在拖动相同的小三角形手柄时向上或向下调整大小。但这似乎不是很直观,因为三角形手柄表明我应该能够沿两个轴调整 textarea 的大小。

我注意到 StackOverflow 在我正在输入我的问题的这个文本区域上有一个修改过的调整大小句柄。它直观地暗示仅垂直调整大小并且看起来很可爱。如果单击 ,您将在textarea 框的底部看到它。我的猜测是它是使用 jQuery 修改的。但是可以使用简单的 CSS 更改调整大小手柄的外观吗?

【问题讨论】:

  • 这只是一个猜测,但我认为他们删除了句柄并创建了自己的句柄。据我所知,您不能修改默认的句柄,因为这是特定于浏览器的。
  • 我刚刚发现尝试右键单击 Stack Overflow rezise 控件非常令人沮丧!
  • 请检查jsfiddle.net/m81wkfe7并根据您的需要替换图像并调整位置
  • 一个简单的解决方案:stackoverflow.com/a/63398119/1405507

标签: javascript css


【解决方案1】:

其实SO answer textarea的HTML部分是:

<div class="wmd-container">
    <div class="wmd-button-bar" id="wmd-button-bar"> .... </div>
    <textarea data-min-length="" tabindex="101" rows="15" cols="92" name="post-text" class="wmd-input processed" id="wmd-input"></textarea>
    <div class="grippie" style="margin-right: 0px;"></div>
</div>

div .grippie 只是一个 SVG 图像,其处理程序设置为侦听您的单击和拖动操作,使用光标高度偏移来动态设置文本区域的高度。

如果您想了解更多信息,请查看this

【讨论】:

    【解决方案2】:

    这不是纯 CSS,而是原生 JavaScript 函数,用于通过拖动底部边缘使任何文本区域垂直调整大小。

    // make textareas resizable by dragging the bottom edge
     
    function init_textareas() {
      use_bottom_edge(document.getElementById("nonlorem"));
      use_bottom_edge(document.getElementById("abitlorem"));
      use_bottom_edge(document.getElementById("morelorem"));
    }
    
    var mouseup_listener = null;
    var mousemove_listener = null;
    var onresize_listener = null;
    
    var initial_y_ergo_resizing = null;
    var initial_height = null;
    var extra = 0;
    
    function use_bottom_edge(target_ta) {
      resize = document.createElement("SPAN");
      resize.classList.add("resize");
      target_ta.parentNode.insertBefore(resize, target_ta.nextSibling);
      target_ta.classList.add("resizeTarget");
      target_ta.style.resize="vertical"; // try "none" to remove handle
      cs = getComputedStyle(target_ta);
      extra = 3 + (parseFloat(cs.getPropertyValue('margin-bottom')) + parseFloat(cs.getPropertyValue('padding-bottom')))/2;
      resize.style.top = target_ta.offsetTop + target_ta.getBoundingClientRect().height - extra + 'px';
      resize.addEventListener('mousedown', resize_onmousedown);
      resize.addEventListener('pointerdown', resize_onpointerdown);
      
      if (mouseup_listener == null) 
        document.addEventListener('mouseup', mouseup_listener=resize_onmouseup);
      if (mousemove_listener == null)
        document.addEventListener('mousemove', mousemove_listener=resize_onmousemove);
      if (onresize_listener == null)
        window.addEventListener('resize', onresize_listener=position_all_resizers);
    }
    
    function resize_onmousedown(e) {
      e.preventDefault();
      target_ta = e.target.previousSibling;
      initial_y_ergo_resizing = e.pageY;
      initial_height = target_ta.getBoundingClientRect().height;
    }
    
    function resize_onpointerdown(e) {
      e.target.setPointerCapture(e.pointerId);
    }
    
    function resize_onmousemove(e) {
      if (initial_y_ergo_resizing != null) {
        e.preventDefault();
        resize = e.target;
        target_ta = resize.previousSibling;
        current_height = initial_height + e.pageY - initial_y_ergo_resizing - 2*extra;
        if (current_height > 20) {
          target_ta.style.height = current_height + "px";
          resize.style.top = target_ta.offsetTop + target_ta.getBoundingClientRect().height - extra + 'px';
        }
      }
    }
    
    function resize_onmouseup(e) {
      if (e.target.classList.contains("resize")) {
        e.preventDefault();
        initial_y_ergo_resizing = null;
        position_all_resizers();
      } else if (e.target.classList.contains("resizeTarget")) {
        position_all_resizers();
      }
    }
    
    function position_all_resizers() {
      resize_array = document.getElementsByClassName("resize");
      for (resize of resize_array) {
        target_ta = resize.previousSibling;
        if (target_ta.offsetParent != null) {
          resize.style.top = target_ta.offsetTop + target_ta.getBoundingClientRect().height - extra + 'px';
          resize.style.display = "block";
        } else {
          resize.style.display = "none";
        }
      }
    }
    .resize, .resize:hover {
      cursor: ns-resize;
      width: 100%;
      height: 7px;
      background-color: transparent; /* try "red" for ghost bars */
      position: absolute;
      display: block;
      opacity: 0.3;
    }
    
    p {
      position: relative; /* to keep bars attached to textarea */
      float: left;
      clear: both;
    }
    <body onload="init_textareas()">
    <p><textarea id="nonlorem">This is lorem ipsum free textarea.</textarea></p>
    <p><textarea id="abitlorem">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</textarea></p>
    <p><textarea id="morelorem">Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea></p>
    </body>

    我只是在每个文本区域之后添加绝对定位的透明“幽灵栏”,在悬停时更改鼠标指针,在鼠标按下时将其锁定,并使用鼠标侦听器根据 y 轴值的变化来修改文本区域的大小。由于可以有多个文本区域,因此在页面布局更改时,我必须遍历所有区域并修改幽灵条的位置。

    准确定位幽灵条有一些技巧,我认为它们总是与文本区域成对出现,因此我可以使用 nextSibling/previousSibling 来解决它们。该代码还支持将幽灵条添加到当前不可见的文本区域(例如,在页面的折叠区域中)。我个人喜欢将句柄保持在右下角作为可以调整文本区域大小的指示器。在实践中,通过鼠标光标的变化很快就会意识到,整个底部边缘都可以用作调整大小的句柄。

    您可以找到类似的带有触摸支持和样式处理的 JavaScript 解决方案 here

    【讨论】:

      猜你喜欢
      • 2011-10-15
      • 2011-12-01
      • 2012-10-19
      • 2018-04-16
      • 1970-01-01
      • 2021-04-15
      • 2015-07-30
      • 2010-10-09
      相关资源
      最近更新 更多