带有标签+现场单元的表单可以包装,但是在包装时排好 [英] Form with label+field units wrappable, but then lining up nicely when wrapped

查看:89
本文介绍了带有标签+现场单元的表单可以包装,但是在包装时排好的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个流体设计表单,由一系列标签和字段组成,我希望它们能够一个接一个地流动,并在必要时包装以支持窗口的宽度。 (标签和输入必须作为一个单元流动,在下一行输入的行的末尾没有悬挂标签。)但是,当它们换行时,我希望字段以整齐的方式排列。有什么方法可以用HTML和CSS来做到这一点? (不幸的是,我必须支持没有CSS3列的旧版浏览器(如果他们甚至可以在这里帮助我的话)。)



我尝试了几件事情,比如给标签(以及跨越其中的)固定长度(您需要点击片段中的全屏按钮,以便片段窗口宽度不固定):



.wrapped-field label {display:inline-block;}。wrapped-字段标签> span {display:inline-block;宽度:8em; < form class =

包装场> <标签> <跨度>短:其中/跨度> < input type =textsize =5> < /标签> <标签> < span>字段的长标签:< / span> < input type =textsize =5> < /标签> <标签> < span>中等标签:< / span> < input type =textsize =5> < /标签> <标签> <跨度>短:其中/跨度> < input type =textsize =5> < /标签> <标签> < span>字段的长标签:< / span> < input type =textsize =5> < /标签> <标签> < span>中等标签:< / span> < input type =textsize =5> < / label>< / form>

$ b

...但由于以下几个原因,这并不令人满意:


  1. 它要求我为标签跨度设置一个固定的大小,标签可以来自配置,所以我不希望在运行时测量它们中的每一个,并将固定大小调整到最大。

  2. 好吧,当他们与每个专栏中最长的标签堆积在一起时:





    ...但是很可怕,例如:



    ...或者:


    理想情况下,每个列将采用其中最长标签或字段的大小(尽管现在所有字段的大小都是相同的),作为响应,作为标签+字段对包装。



    没有HTML / CSS专用解决方案,是否有简单的JavaScript解决方案? (如果没有的话,我会写出复杂的代码;如果这是需要的,不要求人们做大量的代码。)




    • 我使用Bootstrap,所以如果网格系统有帮助(我没有运气),我们可以使用它


    • 如果我们需要JavaScript解决方案,我正在使用jQuery

    • 解决方案

警告:此解决方案使用JavaScript



要使用JavaScript执行此操作,您需要先确定有多少列应该有。如果您在知道列数之前尝试设置宽度,您最终可能会将输入推到最后并导致混乱。



我计算列数的方式是通过将它们全部放在一行中来反向工作。对于每种可能性,我将最大列宽(和其他额外空间)相加,并检查总数是否大于可用空间。如果总数更大,那么我减去一列并再次尝试,从而确保列的最大数量。



最后,当我有一个解决方案时,我将<$每个 span 都是该列的最大宽度,因此所有标签 style.width / code> s在每一列中的大小是相同的。



一个问题是,如果第一列实际上比其他列窄,除第一列外该列中的元素可能无法正确包装。为了解决这个问题,我从可用空间中减去一行中元素的总宽度,然后设置最后一个标签的 margin-right 在每行中添加到该数字(减去4个像素,以确保安全)。



下面是一个工作示例。继续并全屏并调整它的大小;我有一个 resize 事件处理程序,所以它应该可以正常工作。

 0; i--){result = tryGroup(i); if(result){break;如果(!结果){console.log('错误:没有足够的空间');}返回; } var maxWidths = result [0]; var total = result [1]; var size = maxWidths.length; var afterSpace = availableWidth  -  total  -  4; $ elements.each(function setWidths(index,el){var width = maxWidths [index%size]; var parent = el.parentElement; el.style.width = width +'px'; if(index%size === size  -  1){parent.style.marginRight = afterSpace +'px';} else {parent.style.marginRight ='';}}); } alignColumns(); $(window).resize(alignColumns);}); 

.wrapped-field label {display:inline-block;}。wrapped-fields label> span {display:inline-block;宽度:自动; < script src =>< https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js\"></script><form class =wrapped-fields> <标签> <跨度>短:其中/跨度> < input type =textsize =5> < /标签> <标签> < span>字段的长标签:< / span> < input type =textsize =5> < /标签> <标签> < span>中等标签:< / span> < input type =textsize =5> < /标签> <标签> <跨度>微小:其中/跨度> < input type =textsize =5> < /标签> <标签> < span>字段的较长标签:< / span> < input type =textsize =5> < /标签> <标签> < span>中等长标签:< / span> < input type =textsize =5> < / label>< / form>

I have a form in a fluid design consisting of a series of labels and fields, where I want them to flow one after another and wrap down if necessary to support the width of the window. (The label and input must flow as a unit, no dangling label at the end of one row with its input on the next row.) But when they wrap, I want the fields to line up in a tidy way. Is there some way to do this with HTML and CSS? (Unfortunately, I have to support older browsers without CSS3 columns [if they'd even help here].)

I've tried several things, such as giving the labels (well, spans in them) a fixed length (you'll want to click the 'Full Screen' button in the snippet so the snippet window width isn't fixed):

.wrapped-fields label {
  display: inline-block;
}
.wrapped-fields label > span {
  display: inline-block;
  width: 8em;
  white-space: nowrap;
}

<form class="wrapped-fields">
  <label>
    <span>Short:</span>
    <input type="text" size="5">
  </label>
  <label>
    <span>Long label for field:</span>
    <input type="text" size="5">
  </label>
  <label>
    <span>Medium label:</span>
    <input type="text" size="5">
  </label>
  <label>
    <span>Short:</span>
    <input type="text" size="5">
  </label>
  <label>
    <span>Long label for field:</span>
    <input type="text" size="5">
  </label>
  <label>
    <span>Medium label:</span>
    <input type="text" size="5">
  </label>
</form>

...but that's unsatisfactory for several reasons:

  1. It requires that I set a fixed size for the label spans, but the names of those labels can be from configuration and so I don't want to have to measure each of them at runtime and adjust the fixed size to the largest.

  2. It looks okay when they're stacked up with the longest label in each column:

    ...but terrible when they aren't, e.g.:

    ...or:

Ideally, each "column" would take the size of the longest label or field in it (although for now all the fields are the same size), responsively, as the label+field pairs wrapped.

Failing an HTML/CSS-only solution, is there a simple JavaScript solution? (If not, I'll write the complex one; not asking people to do significant amounts of code if that's what it takes.)

If relevant:

  • I'm using Bootstrap, so if the grid system helps (I've had no luck), we could use that

  • I'm using jQuery, if we get into needing a JavaScript solution

解决方案

Warning: this solution uses JavaScript

To do this with JavaScript, you need to first decide how many columns there should be. If you tried setting widths before knowing the number of columns, you could end up pushing an input off the end and getting messed up.

The way I calculate the number of columns is by working backwards from having them all in one row. For each possibility, I add up the maximum column widths (and other extra space) and check if that total is greater than the available space. If the total is greater, then I subtract a column and try again, thus ensuring the maximum number of columns.

Finally, when I have a solution, I set style.width for each span to be the maximum width for that column, so that all labels in each column are the same size.

One gotcha is that if the first column is substantially narrower than the other columns, all but the first element in that column might not wrap correctly. To fix this, I subtract the total widths of the elements in a row from the available space, and then set the margin-right of the last label in each row to that number (minus 4 pixels, to be safe).

Below is a working example. Go ahead and fullscreen and resize it; I have a resize event handler, so it should work.

jQuery(function($) {
  var availableWidth;
  var $elements = $('.wrapped-fields span');
  var widths = [];

  $elements.each(function setWidth() {
    widths.push($(this).width());
  });

  var inputWidth = $elements.first().parent().width() - widths[0];

  function getMaxWidth(size, column) {
    var max = 0;
    var row = 0;
    var length = widths.length;
    var index = column + (size * row);


    while (index < length) {
      width = widths[index];

      if (width > max) {
        max = width;
      }

      row++;
      index = column + (size * row);
    }

    return max;
  }

  function tryGroup(n) {
    // Start with inline-block space
    var total = 4 * (n - 1);
    var maxWidths = [];
    var w;

    var i = 0;
    for (; i < n; i++) {
      w = getMaxWidth(n, i);
      total += w + inputWidth;
      maxWidths.push(w);
    }

    if (total < availableWidth) {
      return [maxWidths, total];
    }
  }

  function alignColumns() {
    // Set the global available width
    availableWidth = $('.wrapped-fields').width();

    var i = widths.length;
    var result;

    for (; i > 0; i--) {
      result = tryGroup(i);

      if (result) {
        break;
      }
    }

    if (!result) {
      console.log('Error: not enough space');
      return;
    }

    var maxWidths = result[0];
    var total = result[1];

    var size = maxWidths.length;
    var afterSpace = availableWidth - total - 4;

    $elements.each(function setWidths(index, el) {
      var width = maxWidths[index % size];
      var parent = el.parentElement;

      el.style.width = width + 'px';

      if (index % size === size - 1) {
        parent.style.marginRight = afterSpace + 'px';
      } else {
        parent.style.marginRight = '';
      }
    });
  }

  alignColumns();

  $(window).resize(alignColumns);
});

.wrapped-fields label {
  display: inline-block;
}

.wrapped-fields label>span {
  display: inline-block;
  width: auto;
  white-space: nowrap;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<form class="wrapped-fields">
  <label>
    <span>Short:</span>
    <input type="text" size="5">
  </label>
  <label>
    <span>Long label for field:</span>
    <input type="text" size="5">
  </label>
  <label>
    <span>Medium label:</span>
    <input type="text" size="5">
  </label>
  <label>
    <span>Tiny:</span>
    <input type="text" size="5">
  </label>
  <label>
    <span>Longer label for field:</span>
    <input type="text" size="5">
  </label>
  <label>
    <span>Medium long label:</span>
    <input type="text" size="5">
  </label>
</form>

这篇关于带有标签+现场单元的表单可以包装,但是在包装时排好的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆