简体   繁体   English

使用包装使最后一个元素占用剩余宽度(并使用IE9支持)

[英]Make last element take remaining width with wrapping (and with IE9 support)

I'm looking for a way to align multiple items next to each other, having them wrap once they fill up the line, and the last item take up the remaining width of the last line . 我正在寻找一种方法来将多个项目彼此相邻对齐,让它们在填满线条时进行换行,最后一个项目占用最后一行的剩余宽度。

I have found multiple questions on a similar topic before, with solutions generally making the items use float: left to align them on a line, and overflow: hidden on the last element which makes it take up the remaining space automatically. 我之前在类似主题上发现了多个问题,解决方案通常使项目使用float: left将它们对齐在一行上,以及overflow: hidden在最后一个元素上,这使得它自动占用剩余空间。 Those solutions work fine in a single line, but they stop working once there are enough items before the last element, that they wrap into multiple lines. 这些解决方案在一行中工作正常,但是一旦在最后一个元素之前有足够的项目,它们就会停止工作,它们会被包装成多行。 Then, the “last” element is still rendered in the first row (if there is enough space), making it no longer be the last element. 然后,“last”元素仍然在第一行中呈现(如果有足够的空间),使其不再是最后一个元素。

However, I want the last element to stay the last element at all times, to have it in the last row—whatever row that is—and automatically take up the remaining space there. 但是,我希望最后一个元素始终保持最后一个元素,将它放在最后一行 - 无论是什么行 - 并自动占用那里的剩余空间。

This is pretty simple with a wrapping flexbox, since you just need to put flex: 0 auto on the former items to make them take up whatever space they need (without taking more), and flex: 1 on the last element to make it take up the remainder. 这是一个非常简单的包装Flexbox,因为你只需要在前面的项目上放置flex: 0 auto以使它们占用他们需要的任何空间(不需要更多),并在最后一个元素上使用flex: 1来实现它余下的。 However, I need to support Internet Explorer 9, so flexbox is unfortunately out of the question. 但是,我需要支持Internet Explorer 9,因此不幸的是,flexbox是不可能的。

This is how the situation looks like. 这就是情况的样子。 When running the snippet, you can use the “Toggle flex box” button to toggle flexbox mode which shows the way it should look like. 当运行片段,您可以使用“切换柔性框”按钮,切换Flexbox的模式,这表明它应该看起来像的方式。

 * { box-sizing: border-box; } .container { width: 300px; background: snow; padding: 5px; overflow: auto; } .element { float: left; margin: 2px 5px 2px 0; background: lavender; } .last { overflow: hidden; } .last > input { width: 100%; } /* Working solution with flex box */ .flex .container { display: flex; flex-wrap: wrap; } .flex .element { flex: 0 auto; } .flex .last { flex: 1; } 
 <div class="container"> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="last"><input type="text" /></div> </div> <div class="container"> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="last"><input type="text" /></div> </div> <button onclick="this.parentNode.classList.toggle('flex')">Toggle flex box</button> 

Here is the solution: 这是解决方案:

  • Add a <div style="clear:left;margin-top:22px"></div> before the .last element* .last元素之前添加<div style="clear:left;margin-top:22px"></div>
  • Add margin-top: -22px; 添加margin-top: -22px; to .last where the amount is about the same as the line-height .last的数量与行高相同
  • If you dont want it to get too small add min-width to .last and it will work as you'd expect 如果你不想让它变得太小,可以将min-width添加到.last ,它会像你期望的那样工作
    Also min-width: 1px; min-width: 1px; is requiered in the class to avoid it getting 0 in special cases. 在课堂上被要求避免在特殊情况下得到0。

Tested and working in IE8+, Edge, Chrome, Opera, Firefox 在IE8 +,Edge,Chrome,Opera,Firefox中经过测试和使用

 * { box-sizing: border-box; } .container { width: 300px; background: snow; padding: 5px; overflow: auto; } .element { float: left; margin: 2px 5px 2px 0; background: lavender; } .last { overflow: hidden; margin-top: -22px; min-width: 1px; } .last > input { width: 100%; } .container .unwrap { clear: left; margin-top: 22px } 
 <div class="container"> <div class="unwrap"></div> <div class="last"><input type="text" /></div> </div> <div class="container"> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="unwrap"></div> <div class="last"><input type="text" /></div> </div> <div class="container"> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz boo</div> <div class="unwrap"></div> <div class="last" style="min-width: 100px"> <input type="text" placeholder="min-width 100px" /> </div> </div> <div class="container"> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="unwrap"></div> <div class="last"><input type="text" /></div> </div> <div class="container"> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="element">Foo baaaaaaaaaaaaaaaaaaaaaaar</div> <div class="unwrap"></div> <div class="last"><input type="text" /></div> </div> <div class="container"> <div class="element">Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz Foo bar baz</div> <div class="unwrap"></div> <div class="last"><input type="text" /></div> </div> 

* margin-top:22px only to avoid the input to slip over in case there are no elements in the container. * margin-top:22px只是为了避免在容器中没有元素的情况下输入滑过。 It should be the absolute value of the negative margin of the input 它应该是输入负边际的绝对值

The following solution isn't perfect, it's using the position hacks. 以下解决方案并不完美,它使用的是位置黑客。 If you disable overflow: hidden; 如果禁用overflow: hidden; you'll see each <input> actually has the same width as the container. 你会看到每个<input>实际上与容器的宽度相同。 But with some CSS visual tweaks, it looks good and may work ok. 但是通过一些CSS视觉调整,它看起来很好并且可以正常工作。

Issue 1: if you type in more characters than it can visually fit, the whole view shifts to the left. 问题1:如果您键入的字符数超出了视觉效果,则整个视图会向左移动。

Workaround 1: set a maxlength value to the <input> might help. 解决方法1:maxlength值设置为<input>可能会有所帮助。

jsfiddle 的jsfiddle

 * { box-sizing: border-box; } .container { width: 300px; background: snow; padding: 5px; position: relative; overflow: hidden; /*hide the overflow*/ } span:after { content: "\\00A0" /*just for one no-break space*/ } input { width: 100%; position: absolute; /*without any top/right/bottom/left value*/ border: 2px solid grey; border-width: 0 0 2px 0; } input:focus { outline: 0; } 
 <div class="container"> <span>FooFoo barFoo bar baz</span> <input type="text" /> </div> <div class="container"> <span>FooFoo barFoo bar bazFooFoo barFoo bar baz bla</span> <input type="text" /> </div> 

And for everybody else, who would like a script option to work with, here is one for you too. 对于其他人,谁想要一个脚本选项来使用,这里也适合你。

Just add data-calcattr to the elements you want to have its width property set to width: calc(100% - ??px); 只需将data-calcattr添加到要将其width属性设置为width: calc(100% - ??px);的元素width: calc(100% - ??px); , where ??px is its current width. ,其中??px是其当前宽度。

Side note: 边注:

The script would likely need adjustments to make up for future borders, margins etc., so this one serves more as one way how to do it. 该脚本可能需要进行调整以弥补未来的边界,边距等,因此这个更适合作为一种方法。

 function calcattr() { var els = document.querySelectorAll('[data-calcattr]'); // TODO: add switch to enable calc. different properties like // get the remaining height as well, by checking the // data-calcattr value, ie: data-calcattr='height' for (i = 0; i < els.length; i++) { els[i].setAttribute("style", "width: 0"); var lpos = parseInt(els[i].getBoundingClientRect().left); var minw = parseFloat(getComputedStyle(els[i]).getPropertyValue('min-width')); var calcwidth = "calc(100% - " + (lpos + 2) + "px)"; els[i].setAttribute("style", "width: " + calcwidth); if ((els[i].getBoundingClientRect().right - lpos) < minw) { els[i].setAttribute("style", "width: 100%"); } } } window.onload = calcattr; (function() { window.addEventListener("resize", resizeThrottler, false); var resizeTimeout; function resizeThrottler() { if ( !resizeTimeout ) { resizeTimeout = setTimeout(function() { resizeTimeout = null; actualResizeHandler(); }, 66); } } function actualResizeHandler() { calcattr(); } }()); 
 * { box-sizing: border-box; } .container { width: 300px; //70%; background: snow; padding: 5px; overflow: auto; } .fullwidth { width: 100%; } .element { float: left; margin: 2px 5px 2px 0; background: lavender; } .last > input { width: 100%; } .last { float: left; min-width: 20px; } 
 <div class="container"> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="last" data-calcattr><input type="text" /></div> </div> <div class="container"> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="last" data-calcattr><input type="text" /></div> </div> <div class="container fullwidth"> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="element">Foo</div> <div class="element">Foo bar</div> <div class="element">Foo bar baz</div> <div class="last" data-calcattr><input type="text" /></div> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM