program tip

목록을 열로 감싸기

radiobox 2021. 1. 8. 08:06
반응형

목록을 열로 감싸기


내가 사용하고 ColdFusionHTML 정렬되지 않은 목록 (포함하는 템플릿을 채울 <ul>들).

이것들의 대부분은 그렇게 길지는 않지만, 몇몇은 말도 안되게 긴 길이를 가지고 있고 실제로 2-3 개의 열에있을 수 있습니다.

이 작업을 쉽게 수행 할 수있는 HTML, ColdFusion 또는 JavaScript (jQuery 솔루션 허용) 방법이 있습니까? 스크롤링을 절약하기 위해 지나치게 복잡한 헤비급 솔루션은 가치가 없습니다.


그래서 나는 A List Apart CSS Swag : Multi-Column Lists 에서이 기사를 파헤 쳤습니다 . 나는 첫 번째 솔루션을 사용하게되었지만 최고는 아니지만 다른 솔루션은 동적으로 생성 할 수없는 복잡한 HTML을 사용하거나 많은 사용자 정의 클래스를 생성해야합니다. 이는 수행 할 수 있지만 많은 인라인 스타일링 및 아마도 거대한 페이지.

다른 솔루션은 여전히 ​​환영합니다.


Safari 및 Firefox 지원이 충분하다면 CSS 솔루션이 있습니다.

ul {
  -webkit-column-count: 3;
     -moz-column-count: 3;
          column-count: 3;
  -webkit-column-gap: 2em;
     -moz-column-gap: 2em;
          column-gap: 2em;
}

Opera에 대해 잘 모르겠습니다.


내가 아는 한 이것을 달성하는 순수한 CSS / HTML 방법은 없습니다. 가장 좋은 방법은 전처리 ( if list length > 150, split into 3 columns, else if > 70, split into 2 columns, else 1) 에서 수행하는 것입니다 .

JavaScript를 사용하는 다른 옵션은 ( 특히 jQuery 라이브러리에 익숙하지 않음 ) 목록을 반복하는 것입니다. 아마도 특정 클래스를 기반으로 목록을 반복하고 자식의 수를 계산하고 충분히 높은 경우 동적으로 첫 번째 이후에 새 목록을 만들고 일부 목록 항목을 새 목록으로 전송합니다. 열을 구현하는 한, 열을 왼쪽으로 띄운 다음 스타일 clear: left또는 clear: both.

.column {
  float: left;
  width: 50%;
}
.clear {
  clear: both;
}
<ul class="column">
  <li>Item 1</li>
  <li>Item 2</li>
  <!-- ... -->
  <li>Item 49</li>
  <li>Item 50</li>
</ul>
<ul class="column">
  <li>Item 51</li>
  <li>Item 52</li>
  <!-- ... -->
  <li>Item 99</li>
  <li>Item 100</li>
</ul>
<div class="clear">


나는 jQuery로 이것을했다-그것은 크로스 플랫폼이고 최소한의 코드이다.

UL을 선택하고 복제 한 다음 이전 UL 뒤에 삽입합니다. 다음과 같은 것 :

$("ul#listname").clone().attr("id","listname2").after()

이전 목록 뒤에 목록 사본이 삽입됩니다. 원래 목록이 float : left로 스타일이 지정되면 나란히 표시되어야합니다.

그런 다음 왼쪽 목록에서 짝수 항목을 삭제하고 오른쪽 목록에서 홀수 항목을 삭제할 수 있습니다.

$("ul#listname li:even").remove();
$("ul#listname2 li:odd").remove();

이제 왼쪽에서 오른쪽으로 두 개의 열 목록이 있습니다.

더 많은 열을 수행하려면 선택기 를 사용 .slice(begin,end)하고 싶을 것 :nth-child입니다. 즉, 21 개의 LI에 대해 .slice(8,14)원래 UL 뒤에 삽입 된 새 UL을 생성 한 다음 원래 UL을 선택하고로 선택한 li를 삭제할 수 ul :gt(8)있습니다.

jQuery에 대한 Bibeault / Katz 책은 훌륭한 리소스입니다.


다음은 Thumbkin의 예 (Jquery 사용) 에 대한 변형입니다 .

var $cat_list = $('ul#catList'); // UL with all list items.
var $cat_flow = $('div#catFlow'); // Target div.
var $cat_list_clone = $cat_list.clone(); // Clone the list.
$('li:odd', $cat_list).remove(); // Remove odd list items.
$('li:even', $cat_list_clone).remove(); // Remove even list items.
$cat_flow.append($cat_list_clone); // Append the duplicate to the target div.

감사합니다 Thumbkin!


다음 JavaScript 코드는 Spidermonkey와 Rhino에서만 작동하며 E4X 노드에서 작동합니다. (서버 측에서는 매우 유용했지만 실제로 구축하기에 충분할만큼 클라이언트에서는 필요하지 않았습니다.)

function columns(x,num) {
    num || (num = 2);
    x.normalize();

    var cols, i, j, col, used, left, len, islist;
    used = left = 0;
    cols = <div class={'columns cols'+num}></div>;

    if((left = x.length())==1)
        left = x.children().length();
    else
        islist = true;

    for(i=0; i<num; i++) {
        len = Math.ceil(left/(num-i));
        col = islist ? new XMLList
                     : <{x.name()}></{x.name()}>;

        if(!islist && x['@class'].toString())
            col['@class'] = x['@class'];

        for(j=used; j<len+used; j++)
            islist ? (col += x[j].copy()) 
                   : (col.appendChild(x.child(j).copy()));

        used += len;
        left -= len;
        cols.appendChild(<div class={'column'+(i==(num-1) ? 'collast' : '')}>{col}</div>);
    }
    return cols;
}

columns(listNode,2)두 개의 열 처럼 호출하면 다음과 같이 바뀝니다.

<ul class="foo">
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>

으로:

<div class="columns cols2">
  <div class="column">
    <ul class="foo">
      <li>a</li>
      <li>b</li>
    </ul>
  </div>
  <div class="column collast">
    <ul class="foo">
      <li>c</li>
    </ul>
  </div>
</div>

다음과 같이 CSS와 함께 사용됩니다.

div.columns {
    overflow: hidden;
    _zoom: 1;
}

div.columns div.column {
    float: left;
}

div.cols2 div.column {
    width: 47.2%;
    padding: 0 5% 0 0;
}

div.cols3 div.column {
    width: 29.8%;
    padding: 0 5% 0 0;
}

div.cols4 div.column {
    width: 21.1%;
    padding: 0 5% 0 0;
}

div.cols5 div.column {
    width: 15.9%;
    padding: 0 5% 0 0;
}

div.columns div.collast {
    padding: 0;
}

대부분의 사람들이 잊고있는 것은 떠 다니는 <li/>항목의 경우 모든 항목의 높이가 동일해야하며 그렇지 않으면 열이 엉망이되기 시작한다는 것입니다.

서버 측 언어를 사용하고 있으므로 CF를 사용하여 목록을 3 개의 배열로 분할하는 것이 좋습니다. 그런 다음 외부 ul사용하여 다음 ul과 같이 3 내부를 감쌀 수 있습니다 .

<cfset thelist = "1,2,3,4,5,6,7,8,9,10,11,12,13">  
<cfset container = []>  
<cfset container[1] = []>  
<cfset container[2] = []>  
<cfset container[3] = []>  

<cfloop list="#thelist#" index="i">  
    <cfif i mod 3 eq 0>  
        <cfset arrayappend(container[3], i)>  
    <cfelseif i mod 2 eq 0>  
        <cfset arrayappend(container[2], i)>  
    <cfelse>  
        <cfset arrayappend(container[1], i)>  
    </cfif>  
</cfloop>  

<style type="text/css"> 
    ul li { float: left; }  
    ul li ul li { clear: left; }  
</style>  

<cfoutput>  
<ul>  
    <cfloop from="1" to="3" index="a">  
    <li>  
        <ul>  
            <cfloop array="#container[a]#" index="i">  
            <li>#i#</li>  
            </cfloop>  
        </ul>  
    </li>  
    </cfloop>  
</ul>  
</cfoutput>

모듈로 연산을 사용하면 </ul><ul>루프 중에 를 삽입하여 목록을 여러 목록으로 빠르게 분할 할 수 있습니다 .

<cfset numberOfColumns = 3 />
<cfset numberOfEntries = 34 />
<ul style="float:left;">
    <cfloop from="1" to="#numberOfEntries#" index="i">
        <li>#i#</li>
            <cfif NOT i MOD ceiling(numberOfEntries / numberOfColumns)>
                </ul>
                <ul style="float:left;">
            </cfif>
    </cfloop>
</ul>

ceiling()대신 사용 round()하여 목록 끝에 추가 값이없고 마지막 열이 가장 짧은 지 확인하십시오.


목록을 여러 그룹화 된 태그로 출력하려면이 방식으로 반복 할 수 있습니다.

<cfset list="1,2,3,4,5,6,7,8,9,10,11,12,13,14">
<cfset numberOfColumns = "3">

<cfoutput>
<cfloop from="1" to="#numberOfColumns#" index="col">
  <ul>
  <cfloop from="#col#" to="#listLen(list)#" index="i" step="#numberOfColumns#">
    <li>#listGetAt(list,i)#</li>
  </cfloop>
  </ul>
</cfloop>
</cfoutput>

다음은 다음 스타일의 열 목록을 허용하는 또 다른 솔루션입니다.

1.      4.      7.       10.
2.      5.      8.       11.
3.      6.      9.       12.

(그러나 순수한 자바 스크립트이며 대체가없는 jQuery가 필요합니다)

다음은 주어진 Array를 주어진 크기의 청크로 나누는 'chunk'라는 새로운 함수를 제공하도록 Array 프로토 타입을 수정하는 코드를 포함합니다. 다음은 UL 선택기 문자열과 열에 포함 할 수있는 행 수를 지정하는 데 사용되는 숫자를 사용하는 'buildColumns'라는 함수입니다. ( 다음은 작동하는 JSFiddle입니다 )

$(document).ready(function(){
    Array.prototype.chunk = function(chunk_size){
        var array = this,
            new_array = [],
            chunk_size = chunk_size,
            i,
            length;

        for(i = 0, length = array.length; i < length; i += chunk_size){
            new_array.push(array.slice(i, i + chunk_size));
        }
        return new_array;
    }

    function buildColumns(list, row_limit) {
        var list_items = $(list).find('li').map(function(){return this;}).get(),
        row_limit = row_limit,
        columnized_list_items = list_items.chunk(row_limit);

        $(columnized_list_items).each(function(i){
            if (i != 0){
                var item_width = $(this).outerWidth(),
                    item_height = $(this).outerHeight(),
                    top_margin = -((item_height * row_limit) + (parseInt($(this).css('margin-top')) * row_limit)),
                    left_margin = (item_width * i) + (parseInt($(this).css('margin-left')) * (i + 1));

                $(this[0]).css('margin-top', top_margin);
                $(this).css('margin-left', left_margin);
            }
        });
    }

    buildColumns('ul#some_list', 5);
});

Flexbox를 사용하여 행 및 열 방향으로 항목을 래핑 할 수 있습니다.

주요 아이디어는 flex-direction컨테이너의을 row또는 로 설정하는 것 입니다 column.

NB : 요즘 브라우저 지원 은 꽤 좋습니다.

깡깡이

( 이 오래된 '별도 목록'기사 에서 가져온 샘플 마크 업 )

ol {
  display: flex;
  flex-flow: column wrap; /* flex-direction: column */
  height: 100px; /* need to specify height :-( */
}
ol ~ ol {
  flex-flow: row wrap; /* flex-direction: row */
  max-height: auto; /* override max-height of the column direction */
}
li {
  width: 150px;
}
a {
  display: inline-block;
  padding-right: 35px;
}
<p>items in column direction</p>
<ol>
  <li><a href="#">Aloe</a>
  </li>
  <li><a href="#">Bergamot</a>
  </li>
  <li><a href="#">Calendula</a>
  </li>
  <li><a href="#">Damiana</a>
  </li>
  <li><a href="#">Elderflower</a>
  </li>
  <li><a href="#">Feverfew</a>
  </li>
  <li><a href="#">Ginger</a>
  </li>
  <li><a href="#">Hops</a>
  </li>
  <li><a href="#">Iris</a>
  </li>
  <li><a href="#">Juniper</a>
  </li>
  <li><a href="#">Kava kava</a>
  </li>
  <li><a href="#">Lavender</a>
  </li>
  <li><a href="#">Marjoram</a>
  </li>
  <li><a href="#">Nutmeg</a>
  </li>
  <li><a href="#">Oregano</a>
  </li>
  <li><a href="#">Pennyroyal</a>
  </li>
</ol>
<hr/>
<p>items in row direction</p>
<ol>
  <li><a href="#">Aloe</a>
  </li>
  <li><a href="#">Bergamot</a>
  </li>
  <li><a href="#">Calendula</a>
  </li>
  <li><a href="#">Damiana</a>
  </li>
  <li><a href="#">Elderflower</a>
  </li>
  <li><a href="#">Feverfew</a>
  </li>
  <li><a href="#">Ginger</a>
  </li>
  <li><a href="#">Hops</a>
  </li>
  <li><a href="#">Iris</a>
  </li>
  <li><a href="#">Juniper</a>
  </li>
  <li><a href="#">Kava kava</a>
  </li>
  <li><a href="#">Lavender</a>
  </li>
  <li><a href="#">Marjoram</a>
  </li>
  <li><a href="#">Nutmeg</a>
  </li>
  <li><a href="#">Oregano</a>
  </li>
  <li><a href="#">Pennyroyal</a>
  </li>
</ol>


Since I had the same problem and couldn't find anything "clean" I thought I'd posted my solution. In this example I use a reversed while loop so I can use splice instead of slice. The advantage now is splice() only needs an index and a range where slice() needs an index and the total. The latter tends to become difficult while looping.

Disadvantage is I need to reverse the stack while appending.

Example:

cols = 4; liCount = 35

for loop with slice = [0, 9]; [9, 18]; [18, 27]; [27, 35]

reversed while with splice = [27, 8]; [18, 9]; [9, 9]; [0, 9]

Code:

// @param (list): a jquery ul object
// @param (cols): amount of requested columns
function multiColumn (list, cols) {
    var children = list.children(),
        target = list.parent(),
        liCount = children.length,
        newUl = $("<ul />").addClass(list.prop("class")),
        newItems,
        avg = Math.floor(liCount / cols),
        rest = liCount % cols,
        take,
        stack = [];

    while (cols--) {
        take = rest > cols ? (avg + 1) : avg;
        liCount -= take;

        newItems = children.splice(liCount, take);
        stack.push(newUl.clone().append(newItems));
    }

    target.append(stack.reverse());
    list.remove();
}

You can try this to convert in cols.

CSS:

ul.col {
    width:50%;
    float:left;
}

div.clr {
    clear:both;
}

Html Part :

<ul class="col">
    <li>Number 1</li>
    <li>Number 2</li>

    <li>Number 19</li>
    <li>Number 20</li>
</ul>
<ul class="col">
    <li>Number 21</li>
    <li>Number 22</li>

    <li>Number 39</li>
    <li>Number 40</li>
</ul>

ReferenceURL : https://stackoverflow.com/questions/4923/wrapping-lists-into-columns

반응형