Hello. Task: Parent element with rubber width (width: 94%, width: 96% and similar variants). Inside the blocks are fixed width (width: 120px or 180px or another size). The number of these blocks is not fixed, it can be from 1 to infinity.

Task: align the current width of the justify parent element.

On pure CSS, this is not done, so go to js (jquery). The only thing that could be found:

$(function () { changeMargin(); }); $(window).resize(function() { changeMargin(); }); function changeMargin() { var container_width = $('div.list').width(); var item_width = $('div.item').width(); var items_count = Math.floor(container_width / item_width); var items_width = item_width * items_count; var difference = container_width - items_width; var margin = difference / (items_count - 1); $('div.item').each(function(index) { if (index > 0 && index % items_count != 0) $(this).css('margin-left', margin+'px'); else $(this).css('margin-left', '0px'); }); } 
 .list { width: 95%; margin: 0 auto; } .item { width: 163px; height: 110px; float: left; background: #ff0; margin-bottom: 10px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> <div class="list"> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> </div> 

But there are two problems: 1. If the elements are not enough even to fill the first and only line, the blocks stick together. - it is necessary in such cases to add indent anyway, at least 10px 2. On small screens, for some reason, the structure is completely broken, i.e. The script defines crookedly where the last element in the line is, and on the new line two elements are stuck together.

Here, too, everything broke ... Tell me, maybe there are options to correctly implement automatic selection of the indent?

alignment

Explanatory picture. Suppose that the width of the blocks is set in styles (the way it is) and is equal to 180px. Depending on the width of the screen, the script calculates how much it can fit and selects indentation for all elements (except the first one if margin-left is used, or the last one if margin-right is used). At the same time, the indent should not be less than 5px. If it does not fit, the block is transferred to the next row. The width of the parent element is not rubber. Also, the blocks also have several widths (for adaptability) - all sizes are written in styles for the desired screen resolutions. Those. the width of the block in the script itself cannot be hardcoded.

  • выровнять по текущей ширине родительского элемента HOW? - Jean-Claude
  • @ Jean-Claude, that is, how? justify - the width of the string. - Aaron
  • so they are so without scripts so filled, learn css selectors - Jean-Claude
  • @ Jean-Claude is nothing like that. by default, you can align left or right or center, but not stretch the existing blocks to the full width of the line of the parent element, automatically adjusting the margin-left or margin-right values, while zeroing the indent of the last block in the line. There are techniques to use justify (pure css), but they are only suitable if the number of blocks is known. + problem with the last line, and the text-align-last property is not cross-browser-like at all. Therefore, the solution is only in js - Aaron
  • shorter horseradish understand how to align, draw a layout of the result. - Jean-Claude

1 answer 1

The problem of sticking together is that the width of the element is returned as an integer, rounded up, so we calculate the width with getBoundingClientRect ()

I try to solve it, everything works:

 $(function() { changeMargin(); $(window).resize(function() { changeMargin(); }); function changeMargin() { var container_width = Math.floor($('div.list')[0].getBoundingClientRect().width); var item_width = $('div.item').width(); var items_count = Math.floor(container_width / item_width); var items_width = item_width * items_count; var difference = container_width - items_width; var margin = Math.floor(difference / (items_count - 1)); if (margin < 10) { items_count -= 1; var items_width = item_width * items_count; var difference = container_width - items_width; var margin = Math.floor(difference / (items_count - 1)); } $('div.item').each(function(index, el) { if ((index > 0) && (index % items_count != 0)) { $(this).css('margin-left', margin + 'px'); } else { $(this).css('margin-left', '0'); } }); } }); 
 .list { width: 95%; margin: 0 auto; } .item { width: 163px; height: 110px; float: left; background: #ff0; margin-bottom: 10px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div class="list"> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> </div> 

Example 2 : The function is designed as a jquery plugin.

 $(function() { $.fn.flex = function() { var element = $(this); var container_width = Math.floor(element[0].getBoundingClientRect().width); var item_width = element.find('.item').width(); var items_count = Math.floor(container_width / item_width); var items_width = item_width * items_count; var difference = container_width - items_width; var margin = Math.floor(difference / (items_count - 1)); if (margin < 10) { items_count -= 1; var items_width = item_width * items_count; var difference = container_width - items_width; var margin = Math.floor(difference / (items_count - 1)); } element.each(function(index, el) { $(el).find('.item').each(function(index, el) { if ((index > 0) && (index % items_count != 0)) { $(this).css('margin-left', margin + 'px'); } else { $(this).css('margin-left', '0'); } }); }); } $('div.list').flex(); $(window).resize(function() { $('div.list').flex(); }); }); 
 .list { width: 95%; margin: 0; overflow: hidden; } .item { width: 163px; height: 110px; float: left; background: #ff0; margin-bottom: 10px; } .list:nth-of-type(even) .item { background-color: #cd4236; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div class="list"> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> </div> <div class="list"> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> <div class="item">Content</div> </div> 

  • Thanks, now the problem with sticking is solved. the only question is: the condition if the indent is less than 10, then the transfer is performed or if (margin <10) {transfer is performed, I understand correctly? - Aaron
  • @Aaron is just protection from small borders, for example 1-2 pixels, yes. It turns out on 1 unit in a row less. - Jean-Claude
  • excellent, thanks again) - Aaron
  • @Aaron added example 2 - designed as a jquery plugin. - Jean-Claude
  • I understand correctly that the plug-in version makes it possible to use this solution at once for several containers containing the same class without duplicating all the code? are there any other differences: speed, resources or something else? - Aaron