开发者

CSS zigzag floating

I'm looking for any idea to get the following working. I need to reorder (only using css!) an unordered list to output its items in a zigzag way - let me explain: Assume we have a simple list:

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <开发者_Python百科;li>9</li>
    <li>10</li>
    <li>11</li>
    <li>12</li>
</ul>

this will output (given a simple float:left):

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

but i'm looking for a way to output like this:

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

why do I need this? I try to change the thumbnail navigation to have two rows instead of one (=> http://landofcoder.com/demo/jquery/lofslidernews/)

But as I can see from the Javascript generating the thumbnail navigation and it's sliding mechanism the only way to make it have two columns and still work properly is to get this funny zigzag order. of course I'm open to any other suggestions :-) thanks in advance!


That's only possible with CSS3, using the new multi-column layout:

http://www.w3.org/TR/css3-multicol/

But as CSS3 has not stabilized yet, the short answer is no, that's not possible.

However, with the introduction of full-page zooming in browsers, you can now make pixel-dependent layouts where previously this was discouraged. You know the size of your columns, so you can align them using different methods.


Well, it's taken a lot longer than I expected (I had to learn how to write a plug-in), but I've finally put something together that does what you want. With a slight caveat, but we'll come to that later.

There's a live demo over on jsbin, showing the list you posted having passed it through the plug-in, I've given it minimal styling, but not extensively. Obviously you can also edit it, for kicks, if you hit the 'Edit using JS Bin' button.

The jQuery is all below, as is a run-through of the options that it can take (at this time):

The Plug-in itself:

Plug-in redacted (replaced by the later incarnation, published below).

How it can be called (as in the jsbin demo):

$(document).ready(
  function() {
    $('#container').wrapSubs({
      rows: 2        
    });
  }
  );

Calling it, as above, will transform your own list (albeit given an id of 'container'):

<ul id="container">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
    <li>11</li>
    <li>12</li>
</ul>

Into the following:

<ul id="container">
        <li id="column_1">
        <ul>
            <li>1</li>
            <li>2</li>
        </ul>
        </li>
        <li id="column_2">
            <ul>
            <li>3</li>
            <li>4</li>
            </ul>
        </li>
        <li id="column_3">
            <ul>
                <li>5</li>
                <li>6</li>
            </ul>
        </li>
        <li id="column_4">
            <ul>
                <li>7</li>
                <li>8</li>
            </ul>
        </li>
        <li id="column_5">
            <ul>
                <li>9</li>
                <li>10</li>
            </ul>
        </li>
        <li id="column_5">
            <ul>
                <li>11</li>
                <li>12</li>
            </ul>
        </li>
    </ul>

Other points:

It can be called on any element that contains children, I haven't exhaustively tested it against the canon of available html elements, but I've verified that it works with:

  • divs,
  • images,
  • spans,
  • lists (except for dl).

It seems to support chaining quite happily, though I've made no effort to have it work with callbacks. Mainly because I've only learned how to write plug-ins in the last four hours or so.

It doesn't do any validation, so garbage in, will give you garbage back. Or, more correctly, a great many html validation errors, but it will faithfully put together the html you give it to work with. It defaults to the assumption that it'll be working with lists, but that can be changed (the linked JS Bin shows it being called on paragraphs and nesting them in blockquotes and divs.

I don't know what else to say, except 'here you go.' =)

Any questions, leave comments. Otherwise, there's just the caveat (the only one I could think of, but there might be more), below.


Caveat: Because I chose to work backwards over the array (to avoid messing with things like indexes in the early stages), you'll find that sometimes all columns but the first has the 'right' number of items, instead of the last.

Obviously I'm happily releasing this to whoever wants to play with it and make it better (it works, and I'm ridiculously proud of myself for having written it, but it could still use improvement and polish) if they'd like.


Edited to include the slightly-revised version of the plug-in:

(function($) {
    $.fn.wrapSubs = function(options) {
    options = $.extend($.fn.wrapSubs.defaults,options);

    // External vars, defaults or from user:
        var rows = options.rows; // number of 'rows' in each column
        var wrapper = options.wrapper; // the item in which 'objects' are wrapped
        var columns = options.columns; // the container of the wrapper
        var idPrefix = options.idPrefix; // the generated columns' id
        var orientation = options.orientation;
        var autofit = options.autofit;
        var thisId = $(this).attr('id');

    // Internal vars, from plug-in itself:  
        var numX = $(this).children().length;
        var cols = Math.ceil(numX/rows);
        var lastX = $(this).find(':last-child').index();

        if (orientation == 'vertical') {
            var colsOrRows = 'col';
            var cellOrientation = 'row';
        }
        else if (orientation == 'horizontal') {
            var colsOrRows = 'row';
            var cellOrientation = 'col';
        }

    // Sanity checks
        if (rows > numX) {
            rows = numX;
        }

            for (i=cols; i>0; i--) {
                $(document.createElement(columns))
                            .attr('id',idPrefix+i)
                            .addClass(orientation)
                            .prependTo($(this));
                $(document.createElement(wrapper))
                            .appendTo($('#'+ idPrefix +i));

                for (c=rows; c>0; c--) {
                    if (numX > 0) {
                        $(this).find(':last').addClass(cellOrientation)
                                .prependTo($('#'+ idPrefix +i+'>' + wrapper));

                        numX--;
                    }                   
                }

            }

        if (autofit && orientation == 'vertical') {
            var numCols = $('#'+thisId).find('.vertical').length;
            var colWidth = Math.floor($('#'+thisId).width()/numCols);
            $('.vertical').css('width',colWidth + 'px');
        }
        else if (autofit && orientation == 'horizontal') {
            var numCols = $('#'+thisId+'> .horizontal:last').find('.col').length;
            var colWidth = Math.floor($('#'+thisId).width()/numCols);
            $('.horizontal').find(columns).css({
                                'width':colWidth,
                                'margin': 0
                                }).parent().css({
                                'margin':0,
                                'width': '100%'});
            console.log(numCols);
        }

        return this;

    }
    $.fn.wrapSubs.defaults = {
        rows: 3,
        wrapper: 'ul',
        columns: 'li',
        idPrefix: 'column_',
        orientation: 'vertical',
        autofit: false
    };
})(jQuery);

This version can do a little more than the previous (now redacted) version:

  1. 'rows', is essentially how many items you want to be grouped together.
  2. 'wrapper', is the container you want each group to grouped-in.
  3. 'columns', is the wrapper for the 'wrapper' (by default this is geared towards processing ul, and a ul can't be a direct descendant of another ul).
  4. 'idPrefix', means this plug-in can be called on multiple elements in the same page (also, see point 7).
  5. 'orientation', means the classes will be sensibly-ish named. 6 'autofit', if autofit is true then the script will auto-fit the 'rows' by the width of their parent.
  6. the script now makes use of the $(this) object throughout, rather than assuming that the item upon which it's being applied is called #container.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜