【问题标题】:Get <input> children of grid to grow and shrink based on content获取网格的 <input> 子元素以根据内容增长和缩小
【发布时间】:2021-11-08 00:01:08
【问题描述】:

在网格中,列可以增长和缩小以填满可用空间,这与每列的内容宽度成正比。请参阅下面示例的&lt;span&gt; 部分。

我也想让&lt;input&gt; 列增长和缩小,就像&lt;span&gt;s 一样。

.grid {
  display: grid;
  grid-template-columns: repeat(2, auto);
  width: 300px;
}

.column {
  border: 1px solid gray;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
<h3>span</h3>
<div class="grid">
  <span class="column" contenteditable></span>
  <span class="column" contenteditable></span>
</div>
<h3>input</h3>
<div class="grid">
  <input class="column" type="text">
  <input class="column" type="text">
</div>

当前行为:

想要的行为:

列应该根据两列宽度之间的比率改变大小这一事实是最重要的目标(在演示中,&lt;span&gt;s 已经这样做了)

我尝试根据其值的 HTML 宽度设置输入的最小宽度和宽度,使用 the createElement method here 计算。但是当设置了 min-width 或 width 时,输入的大小不能再被网格改变,而是网格会调整输入顶部的列的大小,并且椭圆永远不会显示。

我认为无论如何设置宽度都是错误的方法,CSS 可以计算出输入有多少内容吗?

【问题讨论】:

  • 输入没有内容,但有价值。
  • @TemaniAfif 被渲染为内容(事实上,像 MS Edge 这样的一些浏览器甚至在 Inspect Element 中将其显示为影子 DOM 子项)。我希望在 CSS 中找到一种方法来将输入元素的值视为内容。

标签: javascript html jquery css


【解决方案1】:

input 有一个默认设置的size(来自属性大小),但它可以通过width 覆盖。

你可以给size设置一个小值,比如1或2,然后使用javascript根据其内容调整大小。

这是一个使用隐藏span where的想法

  • 输入的值被镜像到里面(注意font-sizefont-family,...),
  • 检索跨度的宽度,然后将其应用回输入。

// deserves to be rewritten . inspired from https://stackoverflow.com/questions/64092841/react-how-to-make-an-input-only-as-wide-as-the-amount-of-text-provided/64094013#64094013
let val = document.querySelectorAll("#text1, #text2, #text3, #text4");
let tpl = document.querySelectorAll("#sptext1, #sptext2, #sptext3, #sptext4");

function resizeIpt() {
  let text1 = val[0].value;
  let text2 = val[1].value;
  let text3 = val[2].value;
  let text4 = val[3].value;
  tpl[0].textContent = text1;
  tpl[1].textContent = text2;
  tpl[2].textContent = text3;
  tpl[3].textContent = text4;
}
let ipt = document.querySelectorAll('.grid input[type="text"]');
for (let i = 0; i < ipt.length; i++) {
  ipt[i].addEventListener("input", function() {
    // onchange ...
    tpl[i].textContent = val[i].value;
    val[i].style.width = "unset"; /* reset actual width */
    resizeIpt;
  });
}
window.onload = resizeIpt;
* {
  box-sizing: border-box;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, auto);
  /* justify-content: left; or start will shrink the columns if contents together are  smaller than 300px of width */
  width: 300px;
  background: #bee
}

.column {
  border: 1px solid gray;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: clamp(2em, min-content, 100%);
  padding: 0 0.5em;
  font-size: inherit;
  font-family: inherit;
}

span[id].column {
  height: 0;
  overflow: hidden;
  border: none;
}
<h3>span</h3>
<div class="grid">
  <span class="column" contenteditable>let it be a really much too long text here </span>
  <span class="column" contenteditable>short</span>
</div>

<h3>input</h3>
<div class="grid">
  <span id="sptext1" class="column"></span>
  <span id="sptext2" class="column"></span>
  <input class="column" size="2" id="text1" type="text" value='let it be a really much too long text here'>
  <input class="column" size="2" id="text1" type="text" value="short">
</div>

<h3>input</h3>
<div class="grid" style="font-family:monospace;">
  <span id="sptext3" class="column"></span>
  <span id="sptext4" class="column"></span>
  <input class="column" size="2" id="text3" type="text" value="short">
  <input class="column" size="2" id="text4" type="text" value='let it be longer'>
</div>

灵感来自React: how to make an input only as wide as the amount of text provided?

【讨论】:

  • 为什么加justify-content: left;
  • 我本可以使用 justify-content:start ;而是遵循文本方向。它使列缩小到其内容。删除它,看看发生了什么;)见developer.mozilla.org/en-US/docs/Web/CSS/justify-content
  • 删除它看起来像我想要的行为
  • 好的,那我误解了你的问题:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-20
  • 2012-07-09
  • 1970-01-01
  • 1970-01-01
  • 2020-03-08
  • 1970-01-01
  • 2013-01-18
相关资源
最近更新 更多