31 votes

Classe de table pour les tables qui, lorsqu'elles sont trop larges, divisent toutes leurs cellules en lignes

Je suis à essayer de comprendre ce que le HTML / CSS, j'ai besoin d'obtenir une certaine rupture de comportement en fonction de combien d'espace est disponible. Fondamentalement, je veux avoir une longue ligne de texte en pause automatiquement à certains endroits, et le tout à un), quand il n'y a plus d'espace pour lui.

Exemple 1:

  • Il y a suffisamment d'espace horizontal pour l'ensemble de la ligne de texte:

    enter image description here

  • Il n'y a pas assez d'espace horizontal pour l'ensemble de la ligne (mais même si il ya de la place pour les deux premiers points, tout se termine sur sa propre ligne) enter image description here

Exemple 2: C'est la même chose que l'exemple précédent, il montre néanmoins que j'aimerais pouvoir les utiliser de manière imbriquée trop:

  • Il y a suffisamment d'espace horizontal pour l'ensemble de la ligne de texte:

    enter image description here

  • Il n'y a pas assez d'espace horizontal pour l'ensemble de la ligne, de sorte que chaque cellule va sur sa propre ligne

    enter image description here

  • Il n'y a pas assez d'espace horizontal pour la deuxième cellule

    enter image description here

Je suis à la recherche d'une solution qui utilise seulement l'HTML et le CSS (ou seulement utilise JavaScript très légèrement) depuis mon intention de cas d'utilisation est l'utilisation de cette jolie lourdement dans le code HTML généré automatiquement pages de documentation.

Je suis venu à travers des exemples comme ces, mais je ne suis pas sûr que je vois comment faire ce travail pour les points (et de la façon de faire ce travail sans l'affectation d'une taille fixe pour chaque cellule - je veux la grandeur de cellule déterminé par son contenu).

Clarfiying modifier

Juste ce qui apporte plus d'importance à une partie cruciale de la question qui a été négligé. Je ne veux plus jamais me retrouver dans un état où il y a deux éléments sur une ligne et le troisième point à la ligne suivante. Les trois éléments doivent aller droit d'être sur une seule ligne pour tous sur des lignes séparées.

13voto

scooterlord Points 1669

Comme je l'ai déjà dit dans les commentaires, ce que l'OP est à la recherche ne peut être réalisé sans l'utilisation de Javascript, c'est ce que je suis venu avec.

D'abord, nous avons une table normale de la structure, nous calculons pour chaque largeur du tableau et appliquer un data-width d'attribut sur chaque table parent ou imbriqués.

Sur redimensionner, dès que chaque tableau est plus long que la largeur de la fenêtre, elle change de contenu d'affichage à partir d' table-cell de block, donc l'empilement de tous les enfants.

Dès que la largeur de la fenêtre est agrandie, elle est comparée à chaque tableau est data-width d'attribut et quand on s'inscrit, on se développe.

edit: je pensais que pour une raison quelconque, il ne serait pas travailler dans certains cas, mais il fonctionne réellement, j'ai donc supprimer les désagréments!

HTML:

<div class="table">
  <div class="cell">
    Content 1
  </div>
  <div class="cell">
    <div class="table">
      <div class="cell">
        Content 1
      </div>
      <div class="cell">
        Cont
      </div>
      <div class="cell">
        Content 3
      </div>    
    </div>
  </div>
  <div class="cell">
    Content 3Content 3Content 3
  </div>

</div>

CSS:

.table {
  display: table;
  border: 1px solid #e4e5e7;
  white-space: nowrap;
}

.cell {
  display: table-cell;
  vertical-align: middle;
  padding: 10px;
  border: 1px solid #e4e5e7;
}

.cell .table {
  margin-bottom: -2px;
}

.table.wrap {
  white-space: normal;
}

.table.wrap > .cell {
  display: block;
}

Javascript:

$('.table').each(function(i) {
  tw = 0;
  $(this).children('.cell').each(function() {
    tw += $(this).outerWidth(true);
  });
  $(this).attr('data-width', tw);
});

$(window).on('load resize', function() {
  w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  $('.table').each(function(i) {
    if ($(this).width() >= w) {
      $(this).addClass('wrap');
    } else if (w >= $(this).attr('data-width')) {
      $(this).removeClass('wrap');    
    }
  });
}).resize();

Et ici, c'est un travail de violon

6voto

Sam Points 1176

Une autre variante avec du JS pur

 window.addEventListener('load', collapse);
window.addEventListener('resize', collapse);

function collapse() {
  var parents = document.querySelectorAll('.parent');
  var children;
  var width;
  for (var i = 0; i < parents.length; i++) {
    parents[i].classList.remove('collapsed');
    width = 0;
    children = parents[i].children;
    for (var j = 0; j < children.length; j++) {
      width += children[j].offsetWidth;
    }
    if (width > parents[i].offsetWidth) {
      parents[i].classList.add('collapsed');
    }
  }
} 
 .parent,
.child {
  border: 1px solid gray;
  margin: 5px;
  padding: 5px;
}

.parent {
  display: flex;
  flex-wrap: wrap;
}

.collapsed {
  display: block;
}

.child {
  flex-grow: 1;
} 
 <div class="parent">
  <div class="child">Some thing one</div>
  <div class="parent child">
    <div class="child">Some inner</div>
    <div class="child">long thing</div>
    <div class="child">two</div>
  </div>
  <div class="child">Thing three</div>
</div> 

1voto

Rounin Points 4260

Une approche consiste à utiliser @media des requêtes pour alterner entre

display: block

et

display: inline-block

Exemple:

.long-row {
display: inline-block;
width: 200px;
padding-left: 4px;
font-size: 16px;
line-height: 32px;
border: 1px solid rgb(0, 0, 0);
}

@media only screen and (min-width: 801px) {
    .long-row {
        display: inline-block;
        float: left;
    }
}

@media only screen and (max-width: 800px) {
    .long-row {
        display: block;
        border-top: none;
    }

    div:first-of-type.long-row {
        border-top: 1px solid rgb(0, 0, 0);
    }
}

@media only screen and (max-width: 600px) {
    .long-row {
    }

    .short-row {
        display: block;
        margin-left: -4px;
        padding-left: 4px;
        border-bottom: 1px solid rgb(0, 0, 0);
    }
    
    span:last-of-type.short-row {
        border-bottom: none;
    }
}
<div class="long-row">Some thing one</div>

<div class="long-row">
<span class="short-row">Some inner</span>
<span class="short-row">long thing</span>
<span class="short-row">two</span>
</div>

<div class="long-row">Thing three</div>

1voto

user10089632 Points 2298

Avant de faire le script, il y a des couples de notes qui doivent être considérés :

À l'état actuel de mes connaissances, cela ne peut être fait en utilisant uniquement CSS. La question est donc comment faire cela à l'aide de JavaScript et avec le meilleur rendement possible? Et je suis venu avec quelques lignes directrices :

  • à l'aide de for boucles qu'ils sont les plus rapides à l'aide de cache du nombre d'itérations
  • en minimisant les appels de fonctions dès que possible

    Éviter :

  • fonctions récursives

  • [].foreach constructions

  • DOM accès chaque fois que possible

En outre, il peut être imbriquées à n'importe quel niveau

L'idée:

Le script prend tous les éléments, de les forcer à une seule ligne, et de voir si il n'y a pas assez d'espace, il les rendre affiché sur le dessus les uns des autres, sinon ils sont restés sur la même ligne.

Il le fait à chaque fois que le document est de balisage est chargé, et quand la fenêtre est redimensionnée.

https://jsfiddle.net/nasdao/qzdtr9ym/

Cheers!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X