web-dev-qa-db-fra.com

Avec CSS, utilisez "..." pour un bloc multi-lignes débordé

avec

overflow: hidden;
text-overflow: Ellipsis;
white-space: nowrap;

"..." sera affiché à la fin de la ligne si débordé . Cependant, cela ne sera affiché que sur une ligne . Mais j'aimerais qu'il soit affiché sur plusieurs lignes.

Cela peut ressembler à:

+--------------------+
|abcde feg hij   dkjd|
|dsji jdia js ajid  s|
|jdis ajid dheu d ...|/*Here it's overflowed, so "..." is shown. */
+--------------------+
297
Ovilia

Il existe également plusieurs plugins jquery qui traitent ce problème, mais beaucoup ne gèrent pas plusieurs lignes de texte. Travaux suivants:

Là aussi quelques tests de préformance .

84
Jim Thomas

J'ai piraté jusqu'à ce que je réussisse à réaliser quelque chose de proche. Il vient avec quelques mises en garde:

  1. Ce n'est pas du pur CSS; vous devez ajouter quelques éléments HTML. Il n'y a cependant pas de JavaScript requis.
  2. L'ellipse est aligné à droite sur la dernière ligne. Cela signifie que si votre texte n'est pas aligné à droite ni justifié, il peut y avoir un écart notable entre le dernier mot visible et les ellipses (en fonction de la longueur du premier mot masqué).
  3. L'espace réservé aux Ellipsis est toujours réservé. Cela signifie que si le texte rentre presque exactement dans la zone, il risque d'être tronqué inutilement (le dernier mot est masqué, même si techniquement, il ne serait pas obligé de le faire).
  4. Votre texte doit avoir une couleur d'arrière-plan fixe, car nous utilisons des rectangles colorés pour masquer l'ellipsis dans les cas où cela n'est pas nécessaire.

Je devrais également noter que le texte sera brisé à une limite de mot, pas à une limite de caractère. C'était délibéré (étant donné que je considère que c'est mieux pour les textes plus longs), mais parce que c'est différent de ce que text-overflow: Ellipsis fait, j'ai pensé que je devrais le mentionner.

Si vous pouvez vivre avec ces mises en garde, le code HTML ressemble à ceci:

<div class="ellipsify">
    <div class="pre-dots"></div>
    <div class="dots">&hellip;</div>
    <!-- your text here -->
    <span class="hidedots1"></span>
    <div class="hidedots2"></div>
</div>

Et ceci est le CSS correspondant, en utilisant l'exemple d'une boîte de 150 pixels de large avec trois lignes de texte sur un fond blanc. Cela suppose que vous avez une réinitialisation CSS ou similaire qui définit les marges et les bourrages à zéro si nécessaire.

/* the wrapper */
.ellipsify {
    font-size:12px;
    line-height:18px;
    height: 54px;       /* 3x line height */
    width: 150px;
    overflow: hidden;
    position: relative; /* so we're a positioning parent for the dot hiders */
    background: white;
}

/* Used to Push down .dots. Can't use absolute positioning, since that
   would stop the floating. Can't use relative positioning, since that
   would cause floating in the wrong (namely: original) place. Can't 
   change height of #dots, since it would have the full width, and
   thus cause early wrapping on all lines. */
.pre-dots {
    float: right;
    height: 36px;  /* 2x line height (one less than visible lines) */
}

.dots {
    float: right; /* to make the text wrap around the dots */
    clear: right; /* to Push us below (not next to) .pre-dots */
}

/* hides the dots if the text has *exactly* 3 lines */
.hidedots1 {
    background: white;
    width: 150px;
    height: 18px;       /* line height */
    position: absolute; /* otherwise, because of the width, it'll be wrapped */
}

/* hides the dots if the text has *less than* 3 lines */
.hidedots2 {
    background: white; 
    width: 150px;
    height: 54px;       /* 3x line height, to ensure hiding even if empty */
    position: absolute; /* ensures we're above the dots */
}

Le résultat ressemble à ceci:

image of the rendered result with different text lengths

Pour clarifier son fonctionnement, voici la même image, sauf que .hidedots1 est surligné en rouge et .hidedots2 en cyan. Ce sont les rectangles qui cachent les Ellipsis quand il n'y a pas de texte invisible:

the same image as above, except that the helper elements are highlighted in color

Testé dans IE9, IE8 (émulé), Chrome, Firefox, Safari et Opera. Ne fonctionne pas dans IE7.

58
balpha

Voici un article récent de css-tricks qui en parle.

Certaines des solutions de l’article ci-dessus (qui ne sont pas mentionnées ici) sont

1) -webkit-line-clamp et 2) Placez un élément parfaitement positionné en bas à droite avec fondu à la fermeture.

Les deux méthodes supposent le balisage suivant:

<div class="module"> /* Add line-clamp/fade class here*/
  <p>Text here</p>
</div>

avec css

.module {
  width: 250px;
  overflow: hidden;
}

1) -webkit-line-clamp

line-clamp FIDDLE (..pour un maximum de 3 lignes)

.line-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;  
  max-height: 3.6em; /* I needed this to get it to work */
}

2) fondu

Supposons que vous définissiez la hauteur de ligne à 1.2em. Si nous voulons exposer Trois lignes de texte, nous pouvons simplement faire la hauteur du conteneur 3,6em (1,2em × 3). Le débordement caché cachera le reste.

Fondu sortant FIDDLE

p
{
    margin:0;padding:0;
}
.module {
  width: 250px;
  overflow: hidden;
  border: 1px solid green;
  margin: 10px;
}

.fade {
  position: relative;
  height: 3.6em; /* exactly three lines */
}
.fade:after {
  content: "";
  text-align: right;
  position: absolute;
  bottom: 0;
  right: 0;
  width: 70%;
  height: 1.2em;
  background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 50%);
}

Solution n ° 3 - Une combinaison utilisant @supports

Nous pouvons utiliser @supports pour appliquer la restriction de ligne de webkit sur les navigateurs de webkit et appliquer le fondu de fondu aux autres navigateurs.

@supports line-clamp avec violon de repli en fondu 

<div class="module line-clamp">
  <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</div>

CSS

.module {
  width: 250px;
  overflow: hidden;
  border: 1px solid green;
  margin: 10px;
}

.line-clamp {
      position: relative;
      height: 3.6em; /* exactly three lines */
    }
.line-clamp:after {
      content: "";
      text-align: right;
      position: absolute;
      bottom: 0;
      right: 0;
      width: 70%;
      height: 1.2em;
      background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 50%);
 }

@supports (-webkit-line-clamp: 3) {
    .line-clamp {
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;  
        max-height:3.6em; /* I needed this to get it to work */
        height: auto;
    }
    .line-clamp:after {
        display: none;
    }
}
41
Danield

Le lien ci-dessous fournit une solution HTML/CSS pure à ce problème.

Prise en charge du navigateur - comme indiqué dans l'article:

Jusqu'ici, nous avons testé sur Safari 5.0, IE 9 (doit être en mode standard), Opera 12 et Firefox 15.

Les navigateurs plus anciens fonctionneront toujours très bien, comme la viande de la mise en page est en positionnement normal, les propriétés de marge et de remplissage. si ton la plate-forme est plus ancienne (par exemple, Firefox 3.6, IE 8), vous pouvez utiliser la méthode mais refait le dégradé en image PNG autonome ou en filtre DirectX.

http://www.mobify.com/dev/multiline-Ellipsis-in-pure-css

le css:

p { margin: 0; padding: 0; font-family: sans-serif;}

.Ellipsis {
    overflow: hidden;
    height: 200px;
    line-height: 25px;
    margin: 20px;
    border: 5px solid #AAA; }

.Ellipsis:before {
    content:"";
    float: left;
    width: 5px; height: 200px; }

.Ellipsis > *:first-child {
    float: right;
    width: 100%;
    margin-left: -5px; }        

.Ellipsis:after {
    content: "\02026";  

    box-sizing: content-box;
    -webkit-box-sizing: content-box;
    -moz-box-sizing: content-box;

    float: right; position: relative;
    top: -25px; left: 100%; 
    width: 3em; margin-left: -3em;
    padding-right: 5px;

    text-align: right;

    background: -webkit-gradient(linear, left top, right top,
        from(rgba(255, 255, 255, 0)), to(white), color-stop(50%, white));
    background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);           
    background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
    background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
    background: linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white); }

le html:

<div class="Ellipsis">
    <div>
        <p>Call me Ishmael.  Some years ago &ndash; never mind how long precisely &ndash; having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world.  It is a way I have of driving off the spleen, and regulating the circulation.  Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off &ndash; then, I account it high time to get to sea as soon as I can.</p>  
    </div>
</div>

le violon

(redimensionner la fenêtre du navigateur pour les tests)

33
Kevin

Après avoir examiné la spécification W3 pour text-overflow , je ne pense pas que cela soit possible en utilisant uniquement CSS. Ellipsis est une propriété new-ish, elle n’a donc probablement pas encore reçu beaucoup d’utilisation ou de commentaires.

Cependant, ce type semble avoir posé une question similaire (ou identique), et quelqu'un a pu proposer une solution Nice jQuery. Vous pouvez tester la solution ici: http://jsfiddle.net/MPkSF/

Si javascript n'est pas une option, je pense que vous avez peut-être plus de chance ...

21
Jeff

Je veux juste ajouter à cette question par souci d'exhaustivité. 

10
Matt

Excellente question ... J'aimerais qu'il y ait une réponse, mais c'est ce que vous pouvez obtenir de plus près avec CSS ces jours-ci. Pas d'Ellipsis, mais toujours très utilisable.

overflow: hidden;
line-height: 1.2em;
height: 3.6em;      // 3 lines * line-height
8
Adam Fraser

Dans votre cas, ce qui suit doit être efficace et suffisant.

  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: Ellipsis;
6
pxthxk

Voici la solution la plus proche que je pourrais obtenir en utilisant simplement CSS.

HTML

<div class="Ellipsis"> <span>...</span>
Hello this is Mr_Green from Stackoverflow. I love CSS. I live in CSS and I will never leave working on CSS even my work is on other technologies.</div>

CSS

div {
    height: 3em;
    line-height: 1.5em;
    width: 80%;
    border: 1px solid green;
    overflow: hidden;
    position: relative;
}
div:after {
    content:". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  . . . . . . . . . . . . . . . . . . . . . . . . . . . .";
    background-color: white;
    color: white;
    display: inline;
    position: relative;
    box-shadow: 8px 1px 1px white;
    z-index: 1;
}
span {
    position: absolute;
    bottom: 0px;
    right: 0px;
    background-color: white;
}

Travailler Fiddle (redimensionner la fenêtre pour vérifier)

Lien vers mon blog pour des explications

Mise à jour Fiddle

J'espère maintenant qu'un expert en CSS aurait eu une idée sur la façon de le rendre parfait. :)

6
Mr_Green

J'ai trouvé cette solution css (scss) qui fonctionne assez bien. Sur les navigateurs Web, il affiche l’Ellipsis et sur d’autres navigateurs, il ne fait que tronquer le texte. Ce qui est bien pour mon usage prévu.

$font-size: 26px;
$line-height: 1.4;
$lines-to-show: 3;

h2 {
  display: block; /* Fallback for non-webkit */
  display: -webkit-box;
  max-width: 400px;
  height: $font-size*$line-height*$lines-to-show; /* Fallback for non-webkit */
  margin: 0 auto;
  font-size: $font-size;
  line-height: $line-height;
  -webkit-line-clamp: $lines-to-show;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: Ellipsis;
}

Un exemple du créateur: http://codepen.io/martinwolf/pen/qlFdp

6
Nikola Lajic

Un peu tard pour cette soirée, mais j’ai trouvé ce que je pense être une solution unique. Plutôt que d’essayer d’insérer votre propre Ellipsis dans une ruse CSS ou js, j’ai pensé que j’essaierais de rouler avec la restriction d’une seule ligne. Donc, je duplique le texte pour chaque "ligne" et utilise juste un retrait négatif pour m'assurer qu'une ligne commence là où la dernière s'arrête. VIOLON

CSS:

#wrapper{
    font-size: 20pt;
    line-height: 22pt;
    width: 100%;
    overflow: hidden;
    padding: 0;
    margin: 0;
}

.text-block-line{
    height: 22pt;
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    white-space: nowrap;
    width: auto;
}
.text-block-line:last-child{
    text-overflow: Ellipsis;
}

/*the follwing is suboptimal but neccesary I think. I'd probably just make a sass mixin that I can feed a max number of lines to and have them avialable. Number of lines will need to be controlled by server or client template which is no worse than doing a character count clip server side now. */
.line2{
    text-indent: -100%;
}
.line3{
    text-indent: -200%;
}
.line4{
    text-indent: -300%;
}

HTML:

<p id="wrapper" class="redraw">
    <span class="text-block-line line1">This text is repeated for every line that you want to be displayed in your element. This example has a max of 4 lines before the Ellipsis occurs. Try scaling the preview window width to see the effect.</span>
    <span class="text-block-line line2">This text is repeated for every line that you want to be displayed in your element. This example has a max of 4 lines before the Ellipsis occurs. Try scaling the preview window width to see the effect.</span>
    <span class="text-block-line line3">This text is repeated for every line that you want to be displayed in your element. This example has a max of 4 lines before the Ellipsis occurs. Try scaling the preview window width to see the effect.</span>
    <span class="text-block-line line4">This text is repeated for every line that you want to be displayed in your element. This example has a max of 4 lines before the Ellipsis occurs. Try scaling the preview window width to see the effect.</span>
</p>

Plus de détails dans le violon. Il y a un problème avec le navigateur qui refait une nouvelle utilisation pour laquelle j'utilise un redessin JS, alors vérifiez-le, mais c'est le concept de base. Toutes les pensées/suggestions sont très appréciées.

4
lupos

merci @balpha et @ Kevin, je combine deux méthodes ensemble. 

pas besoin de js dans cette méthode.

vous pouvez utiliser background-image et aucun dégradé nécessaire pour masquer les points.

la innerHTML de .Ellipsis-placeholder n'est pas nécessaire, j'utilise .Ellipsis-placeholder pour conserver les mêmes largeur et hauteur avec .Ellipsis-more. Vous pouvez utiliser display: inline-block à la place.

.Ellipsis {
    overflow: hidden;
    position: relative;
}
.Ellipsis-more-top {/*Push down .Ellipsis-more*/
    content: "";
    float: left;
    width: 5px;
}
.Ellipsis-text-container {
    float: right;
    width: 100%;
    margin-left: -5px;
}
.Ellipsis-more-container {
    float: right;
    position: relative;
    left: 100%;
    width: 5px;
    margin-left: -5px;
    border-right: solid 5px transparent;
    white-space: nowrap;
}
.Ellipsis-placeholder {/*keep text around ,keep it transparent ,keep same width and height as .Ellipsis-more*/
    float: right;
    clear: right;
    color: transparent;
}
.Ellipsis-placeholder-top {/*Push down .Ellipsis-placeholder*/
    float: right;
    width: 0;
}
.Ellipsis-more {/*Ellipsis things here*/
    float: right;
}
.Ellipsis-height {/*the total height*/
    height: 3.6em;
}
.Ellipsis-line-height {/*the line-height*/
    line-height: 1.2;
}
.Ellipsis-margin-top {/*one line height*/
    margin-top: -1.2em;
}
.Ellipsis-text {
    Word-break: break-all;
}
<div class="Ellipsis ellipsis-height Ellipsis-line-height">
    <div class="Ellipsis-more-top Ellipsis-height"></div>
    <div class="Ellipsis-text-container">
        <div class="Ellipsis-placeholder-top Ellipsis-height Ellipsis-margin-top"></div>
        <div class="Ellipsis-placeholder">
           <span>...</span><span>more</span>
        </div>
        <span class="Ellipsis-text">text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text </span>
    </div>
    <div class="Ellipsis-more-container Ellipsis-margin-top">
        <div class="Ellipsis-more">
            <span>...</span><span>more</span>
        </div>
    </div>
</div>

jsfiddler

3
Defims

Il y a beaucoup de réponses ici mais j'en avais besoin d'une:

  • CSS uniquement
  • Résistant pour le futur (devient plus compatible avec le temps)
  • Ne va pas séparer les mots (seulement les espaces)

La mise en garde est qu'il ne fournit pas d'ellipsis pour les navigateurs qui ne prennent pas en charge la règle -webkit-line-clamp (actuellement, IE, Edge, Firefox), mais qu'il utilise un dégradé pour atténuer leur texte.

.clampMe {
  position: relative;
  height: 2.4em; 
  overflow: hidden;
}

.clampMe:after {
  content: "";
  text-align: right;
  position: absolute;
  bottom: 0;
  right: 0;
  width: 50%;
  height: 1.2em; /* Just use multiples of the line-height */
  background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 80%);
}

/* Now add in code for the browsers that support -webkit-line-clamp and overwrite the non-supportive stuff */
@supports (-webkit-line-clamp: 2) {
  .clampMe {
      overflow: hidden;
      text-overflow: Ellipsis;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
  }
  
  .clampMe:after {
    display: none;
  }
}
<p class="clampMe">There's a lot more text in here than what you'll ever see. Pellentesque habitant testalotish morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>

Vous pouvez le voir en action dans ce CodePen et vous pouvez également voir une version Javascript ici (pas de jQuery).

3
NilsyNils

la solution javascript sera meilleure

  • obtenir le nombre de lignes de texte
  • basculer la classe is-Ellipsis si la fenêtre est redimensionnée ou modifiée

getRowRects

Element.getClientRects() fonctionne comme this

enter image description here

chaque rects de la même ligne a la même valeur top, alors découvrez les rects avec une valeur top différente, comme this

enter image description here

function getRowRects(element) {
    var rects = [],
        clientRects = element.getClientRects(),
        len = clientRects.length,
        clientRect, top, rectsLen, rect, i;

    for(i=0; i<len; i++) {
        has = false;
        rectsLen = rects.length;
        clientRect = clientRects[i];
        top = clientRect.top;
        while(rectsLen--) {
            rect = rects[rectsLen];
            if (rect.top == top) {
                has = true;
                break;
            }
        }
        if(has) {
            rect.right = rect.right > clientRect.right ? rect.right : clientRect.right;
            rect.width = rect.right - rect.left;
        }
        else {
            rects.Push({
                top: clientRect.top,
                right: clientRect.right,
                bottom: clientRect.bottom,
                left: clientRect.left,
                width: clientRect.width,
                height: clientRect.height
            });
        }
    }
    return rects;
}

float ...more

comme ceci

enter image description here

détecter le redimensionnement de la fenêtre ou le changement d'élément

comme ceci

enter image description here

enter image description here

enter image description here

2
Defims

une méthode pure css basée sur -webkit-line-clamp:

@-webkit-keyframes Ellipsis {/*for test*/
    0% { width: 622px }
    50% { width: 311px }
    100% { width: 622px }
}
.Ellipsis {
    max-height: 40px;/* h*n */
    overflow: hidden;
    background: #eee;

    -webkit-animation: Ellipsis ease 5s infinite;/*for test*/
    /**
    overflow: visible;
    /**/
}
.Ellipsis .content {
    position: relative;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-box-pack: center;
    font-size: 50px;/* w */
    line-height: 20px;/* line-height h */
    color: transparent;
    -webkit-line-clamp: 2;/* max row number n */
    vertical-align: top;
}
.Ellipsis .text {
    display: inline;
    vertical-align: top;
    font-size: 14px;
    color: #000;
}
.Ellipsis .overlay {
    position: absolute;
    top: 0;
    left: 50%;
    width: 100%;
    height: 100%;
    overflow: hidden;

    /**
    overflow: visible;
    left: 0;
    background: rgba(0,0,0,.5);
    /**/
}
.Ellipsis .overlay:before {
    content: "";
    display: block;
    float: left;
    width: 50%;
    height: 100%;

    /**
    background: lightgreen;
    /**/
}
.Ellipsis .placeholder {
    float: left;
    width: 50%;
    height: 40px;/* h*n */

    /**
    background: lightblue;
    /**/
}
.Ellipsis .more {
    position: relative;
    top: -20px;/* -h */
    left: -50px;/* -w */
    float: left;
    color: #000;
    width: 50px;/* width of the .more w */
    height: 20px;/* h */
    font-size: 14px;

    /**
    top: 0;
    left: 0;
    background: orange;
    /**/
}
<div class='Ellipsis'>
    <div class='content'>
        <div class='text'>text text text text text text text text text text text text text text text text text text text text text </div>
        <div class='overlay'>
            <div class='placeholder'></div>
            <div class='more'>...more</div>
        </div>
    </div>
</div>

0
Defims
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical; 

voir plus cliquez ici

0
elrrrrrrr