CSS: dernier élément en ligne

J'ai une liste [inline] non ordonnée de liens qui s'enroule sur deux lignes:
widget liens

<ul>
    <li><a href="http://google.com">Harvard Medical School</a></li>
    <li><a href="http://google.com">Harvard College</a></li>
    ...
</ul>

J'ajoute le séparateur de points via un pseudo-élément CSS:

#widget-links li { display: inline; }
#widget-links li:after { content: " 0b7"; }

Malheureusement, le séparateur apparaît après le dernier élément sur chaque ligne. Avec une seule ligne, je voudrais simplement saisir :last-child et supprimer l'élément psuedo.

Des astuces astucieuses pour cacher ce dernier point avec plus d'une ligne? Je suis ouvert à css bizarre, ou JavaScript si absolument nécessaire.

31
demandé sur benesch 2012-03-24 03:17:42

6 réponses

Question intéressante! Voici ce que je considère comme une solution "low-tech" avec jQuery qui fait l'affaire:

$(function() {
    var lastElement = false;
    $("ul > li").each(function() {
        if (lastElement && lastElement.offset().top != $(this).offset().top) {
            lastElement.addClass("nobullet");
        }
        lastElement = $(this);
    }).last().addClass("nobullet");
});​

L'algorithme n'est pas difficile à suivre, mais voici l'idée: itérer sur les éléments, en profitant qu'ils ont tous les mêmes propriétés (taille, marge, affichage en ligne, etc.) qui affectent leur position lorsque le navigateur calcule la mise en page. Comparez le décalage vertical de chaque élément avec celui du précédent; s'ils diffèrent, le précédent doit avoir été à la fin de la ligne donc marquer pour un traitement spécial. Enfin, marque le dernier élément dans l'ensemble d'un traitement spécial, puisque, par définition, c'est le dernier élément de la ligne sur laquelle il apparaît.

IMHO le fait que c'est une solution basée sur Javascript (peut - il être fait sans, je me demande?) n'y a aucun problème ici, car même si le script ne s'exécute pas, il n'y aura qu'une très légère dégradation visuelle de votre page Web.

Le Voir en action.

28
répondu Jon 2012-03-23 23:46:07

Je suis confronté à la même situation, et le faire dans un design réactif. voici ma seule solution CSS.

div {
  overflow: hidden;
  margin: 1em;
}
div ul {
  list-style: none;
  padding: 0;
  margin-left: -4px;
}
div ul li {
  display: inline;
  white-space: nowrap;
}
div ul li:before {
  content: " \00b7";
}
<div>
  <ul>
    <li>item 1</li>
    <li>item B</li>
    <li>item 3</li>
    <li>item IV</li>
    <li>the long item</li>
    <li>item 6</li>
    <li>item 7</li>
    <li>item awesome</li>
    <li>give me your money</li>
    <li>contact</li>
    <li>menu item more</li>
    <li>CSS is awesome</li>
    <li>CSS3 is great</li>
    <li>more</li>
    <li>last item</li>

  </ul>
</div>

Ici, il est aussi comme un violon

5
répondu Chad 2016-02-26 21:06:38

En fait, j'ai trouvé un défaut dans la solution de Jon : dans la situation rare où deux (ou plus) lis tiennent sur une rangée, mais les deux li S plus la balle ne rentrent pas, ils se rendraient l'un à côté de l'autre sans balle. (Avoir la puce là à l'origine ferait que les deux li S soient sur des lignes séparées, en appliquant la classe nobullet et en réduisant l'espacement, en déplaçant le second li vers le haut d'une ligne.)

Voici un exemple de la faille: http://jsfiddle.net/W2ULx/61/ (Avis dans la première ligne, les deux derniers lis sont rendus sans balle entre eux. La seule chose qui a changé par rapport au violon d'origine est la largeur du ul pour forcer le problème.)

La solution simple que j'ai trouvée était de changer dans le CSS

ul li.nobullet:after { content: none; }

À

ul li.nobullet:after { color: transparent; }

De sorte qu'au lieu de supprimer l'espacement, il le rend invisible. Tout ce qui aurait brisé une nouvelle ligne se cassera toujours à une nouvelle ligne, au lieu d'être cogné une ligne par la balle enlevée.

3
répondu Randall Bruder 2017-05-23 11:47:14

Je voulais une version qui serait visuellement centrée et qui traiterait également du bogue de re-mise en page que Randall manipulerait avec élégance. Cette solution ajoute également un point central et un espace au premier élément de chaque ligne, ce qui contrebalance le point central et l'espace à la fin de chaque ligne. Vous pouvez les supprimer si vous alignez votre menu.

Je suis également passé à offset ().laissé dans le code parce que Firefox ne fonctionnait pas avec offset ().haut.

Le code est ci-dessous, mais voici un lien pour vous pouvez plus facilement le voir fonctionner. http://kpao.typepad.com/files/middle-dot-separated-list-v2.html

<html>
<head>
<title>Wildlife Conservation Network programs menu</title>
<style>
body, div, p, div, li, a {font-family:"Avenir Next","Segoe UI",sans-serif; font-size:15px;}
a {color:royalblue; text-decoration:none;}
a:hover, a:active {text-decoration:underline;}
ul.menu {background-color:#f2f2f2; text-align:center; padding:1em 0; margin:0;}
ul li {display:inline; white-space:nowrap;}
ul li::before {content:""; padding-right:3px;}
ul li::after {content:"\00a0\00b7"; padding-left:3px;}
ul li.firstdot::before, ul li:first-child::before {content:"\00b7\00a0"; color:transparent;}
ul li.lastdot::after,  ul li:last-child::after {color:transparent;}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
function midDotIt() {
    var lastElement = false;
    $("ul li").each(function() {
        if (lastElement && lastElement.offset().left > $(this).offset().left) {
            $(lastElement).addClass("lastdot");
            $(this).addClass("firstdot");
       } else if (lastElement) {
            $(lastElement).removeClass("lastdot");
            $(this).removeClass("firstdot");
       }
        lastElement = $(this);
   });
}
</script>
</head>
<body onload="midDotIt();" onresize="midDotIt();">

<ul class="menu">
<li><a href="https://wildnet.org/wildlife-programs/african-wild-dog">African Wild Dog</a></li>
<li><a href="https://wildnet.org/wildlife-programs/andean-cat">Andean Cat</a></li>
<li><a href="https://wildnet.org/wildlife-programs/cheetah-botswana">Cheetah - Botswana</a></li>
<li><a href="https://wildnet.org/wildlife-programs/cheetah-namibia">Cheetah - Namibia</a></li>
<li><a href="https://wildnet.org/wildlife-programs/cotton-top-tamarin">Cotton-Top Tamarin</a></li>
<li><a href="https://wildnet.org/wildlife-programs/elephant">Elephant</a></li>
<li><a href="https://wildnet.org/wildlife-programs/elephant-crisis-fund">Elephant Crisis Fund</a></li>
<li><a href="https://wildnet.org/wildlife-programs/ethiopian-wolf">Ethiopian Wolf</a></li>
<li><a href="https://wildnet.org/wildlife-programs/grevys-zebra">Grevy&#039;s Zebra</a></li>
<li><a href="https://wildnet.org/wildlife-programs/lion-ewaso">Lion - Ewaso</a></li>
<li><a href="https://wildnet.org/wildlife-programs/lion-niassa-0">Lion - Niassa</a></li>
<li><a href="https://wildnet.org/wildlife-programs/lion-recovery-fund">Lion Recovery Fund</a></li>
<li><a href="https://wildnet.org/wildlife-programs/okapi">Okapi</a></li>
<li><a href="https://wildnet.org/wildlife-programs/penguin">Penguin</a></li>
<li><a href="https://wildnet.org/wildlife-programs/saiga-antelope">Saiga Antelope</a></li>
<li><a href="https://wildnet.org/wildlife-programs/sharks-rays">Sharks and Rays</a></li>
<li><a href="https://wildnet.org/wildlife-programs/small-wild-cats">Small Wild Cats</a></li>
<li><a href="https://wildnet.org/wildlife-programs/snow-leopard">Snow Leopard</a></li>
<li><a href="https://wildnet.org/wildlife-programs/spectacled-bear">Spectacled Bear</a></li>
<li><a href="https://wildnet.org/what-we-do/scholarships">Scholarship Program</a></li>
</ul>
</body>
</html>
1
répondu Dave C 2017-08-26 13:53:05

Voici une version JavaScript seulement de la réponse acceptée (Pas de jQuery nécessaire!):

document.addEventListener("DOMContentLoaded", function(event) {
    var lastElement = false;
    var els = document.querySelectorAll('ul li');
    for(var i = 0; i < els.length; i++){
        var el = els[i]; // current element
        if (lastElement && lastElement.offsetTop !== el.offsetTop) {
            lastElement.className += " nobullet";
        }
        lastElement = el;
    }
    els[els.length - 1].className += " nobullet";
});

Mise à jour

Voici une autre façon si vous avez besoin de garder une trace des positions réelles des éléments dans chaque ligne (Groupe):

var i = 0;
var j = 0;
var keys = [];
var groupsList = [];
$("ul li").each(function() {
    var topOffset = $(this).offset().top;
    if(Array.isArray(groupsList[topOffset])) {
        groupsList[topOffset].push(i);
    } else {
        if(j > 0) {
            var lastElementIndexOnRow = groupsList[keys[j-1]][groupsList[keys[j-1]].length - 1];
            $($('ul li').get(lastElementIndexOnRow)).addClass('nobullet');
        }
        groupsList[topOffset] = [];
        groupsList[topOffset].push(i);
        keys.push(topOffset);
        j++;
    }
    i++;
}).last().addClass("nobullet");
0
répondu Vahid Amiri 2017-09-30 04:41:54

Basé sur la réponse acceptée dans le café:

do lastinline = ->
        $('[lastinline]').each ->
            $parent = $ @
            lastElement = false
            $parent.find('> *').each ->
                $child = $ @
                if lastElement && lastElement.offset().top != $child.offset().top
                    lastElement.addClass "last-in-line"
                lastElement = $child

            .last().addClass "last-in-line"

$(window).on 'resize', lastinline
-1
répondu zsitro 2015-11-02 11:09:15