简体   繁体   中英

Detecting line-breaks in an unordered list

Concerning horizontal, unordered lists that utilize :before or :after insertion of dividers between list items.

I had resigned myself to spot checking at predetermined intervals whether or not a list's children had broken into another line, and was somewhat satisfied that at least the list looked right at my tweak points.

Bit of a short-sighted solution , however, as problems arose whenever my client wanted to change the content of any given child. Pretty tedious work :\\ The problem was further compounded when it was decided to switch to a different divider symbol, as each page that contained one of these lists had custom CSS embedded that would also need to be changed. Long story short, I had pretty much given up trying to keep it clean.

EDIT:

To be clear, the issue is that there is no clear way in CSS (that I'm aware of) to detect a line-break in a list. If you insert dividers between list items, and the list breaks into a new line, you're left with the last item on the first line with a divider hanging out on the end. Unsightly. The only other way I've been able to tackle it before is with tweak points in CSS, but that is less than an ideal fix, because if the list changes at all, you have to go back and re-check the tweak points.

EDIT2:

Attaching image to help clarify intention

在此处输入图片说明

I've come up with a solution today that I'm pretty satisfied with, so I thought I'd share it for posterity's sake, in case anyone else out there is also struggling with a similar problem. I'm also very interested in solutions anyone else may have come up with, especially if the solution is CSS-only.

CSS:

.classname {
    padding-left:0;
}
.classname.centered {
    text-align:center;
}
.classname.left {
    text-align:left;
}
.classname li {
    display:inline;
    margin:0;
    padding:0;
    white-space: nowrap;    
}
.classname li:not(.last-on-line):not(:last-of-type):after {
    content:"|";
    margin:0 0.25em 0 0.45em;
}

.classname.centered li:first-of-type,
.classname.centered li.first-on-line {
    padding-left:0.8875em;
}

.classname.centered li:last-of-type,
.classname.centered li.last-on-line,
.classname.left li:last-of-type,
.classname.left li.last-on-line {
    padding-right:0.8875em;
}

JS:

function determineListLineBreak() {
    //..
    var matchingDisplayTypes = ['inline','inline-block'];
    //..
    $('ul').each(function() {
        //..
        var listParent = this;
        //..
        if ($(this).hasClass('classname') == true && $(this).find('li').length > 1) {
            //..
            if ($.inArray($(this).find('li').css('display'), matchingDisplayTypes) > -1) {
                //..
                var listItems = $(this).find('li'),
                    listItemCount = $(this).find('li').length,
                    listItemLoopCount = 0;
                //..
                $(listItems).each(function() {
                    //..
                    listItemLoopCount = listItemLoopCount + 1;
                    //..
                    $(this).removeClass('first-on-line').removeClass('last-on-line');
                    //..
                    if (listItemLoopCount == listItemCount) {
                        //..
                        $(listItems).each(function() {
                            //..                    
                            var listItem = this;
                            //..
                            var itemToCompare,
                                compareDirection;
                            //..
                            if ($(listItem).next().length) {                        
                                itemToCompare = $(listItem).next(),
                                compareDirection = 'next';
                            }
                            else {
                                itemToCompare = $(listItem).prev(),
                                compareDirection = 'prev';
                            }
                            //..
                            if ($(listItem).offset().top != $(itemToCompare).offset().top) {
                                //..
                                if (compareDirection == 'next') {
                                    $(listItem).addClass('last-on-line');
                                    $(itemToCompare).addClass('first-on-line');
                                }
                                else {
                                    $(listItem).addClass('first-on-line');
                                    $(itemToCompare).addClass('last-on-line');
                                }
                            }
                        });
                    }
                });
            }
        }
    });
}

$(document).ready(function() {
    determineListLineBreak();
});

$(window).resize(function() {
    setTimeout(determineListLineBreak, 0)
});

HTML:

<ul class="classname left">
    <li>This is a list item</li>
    <li>This is another list item</li>
    <li>An item?</li>
    <li>Yes.</li>
    <li>Are we done?</li>
    <li>This is getting boring</li>
</ul>
<ul class="classname centered">
    <li>This is a list item</li>
    <li>This is another list item</li>
    <li>An item?</li>
    <li>Yes.</li>
    <li>Are we done?</li>
    <li>This is getting boring</li>
</ul>

Explanation for those that need it:

All I did was measure the distance to the top of the page from each list item, and then compare the measurements of a list item and the list item immediately before it. If the distance is different, it adds a class to the list item before the line-break (I also included the addition of a class to the list item that starts the new line, for those who might need that). CSS takes care of the rest.

Thanks for reading, hope this helps you!

EDIT:

So I found out that as you get close to breaking the line, you sometimes see the item on the edge taking on both classes, with the item that should no longer be last having the "last class" as well. I think this has to do with the space that the divider takes up is "disappearing", allowing what would have gone to the next line to come back "up".

The workaround I'm employing now seems a bit much. I feel like this should be easier and I'm just missing it. I wasn't paying close enough attention the first time I checked it over (wasn't resizing slow enough), but now the added JS/CSS seems to have it nearly perfect. I can still break it if I really try though, so I could use some help, or if anyone has a better solution, I'd appreciate it.

EDIT2:

So, turns out this can be broken too, I'll have to keep working on it.. This gets you close if you aren't super picky. Good enough for me for now

EDIT3:

I've edited the code more, to fix some things and to include left-aligned orientation.

Fiddle http://jsfiddle.net/u5uzg02w/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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