CSS: truncar las celdas de la tabla, pero encajar tanto como sea posible

223

Conoce a Fred El es una mesa:

Una celda tiene más contenido y es más ancha, la otra tiene menos contenido y es más estrecha

<table border="1" style="width: 100%;">
    <tr>
        <td>This cells has more content</td>
        <td>Less content here</td>
    </tr>
</table>

El departamento de Fred tiene la extraña costumbre de cambiar de tamaño, por lo que aprendió a ocultar parte de su contenido para no empujar a todas las demás unidades y empujar la sala de estar de la Sra. Whitford al olvido:

Las celdas ahora tienen el mismo tamaño, pero solo una tiene su contenido truncado, y parece que si la otra celda da un espacio en blanco, ambos podrían encajar.

<table border="1" style="width: 100%; white-space: nowrap; table-layout: fixed;">
    <tr>
        <td style="overflow: hidden; text-overflow: ellipsis">This cells has more content</td>
        <td style="overflow: hidden; text-overflow: ellipsis">Less content here</td>
    </tr>
</table>

Esto funciona, pero Fred tiene la persistente sensación de que si su celda derecha (a la que ha apodado Celldito) cede un poco de espacio, su celda izquierda no se truncará la mayor parte del tiempo. ¿Puedes salvar su cordura?


En resumen: ¿cómo pueden desbordarse las celdas de una tabla de manera uniforme, y solo cuando han renunciado a todo su espacio en blanco?

s4y
fuente
95
+1 Para la caracterización de un objeto virtual, muy bien un señor :)
Myles Gray
66
Sospecho que tendrá que recurrir a JavaScript para resolver esto.
thirtydot
66
Lolz .. +1 por valor de entretenimiento :) ... ¿esto tiene que ser dinámico o no puede simplemente establecer un ancho en cada columna?
Guerra

Respuestas:

82
<table border="1" style="width: 100%;">
    <colgroup>
        <col width="100%" />
        <col width="0%" />
    </colgroup>
    <tr>
        <td style="white-space: nowrap; text-overflow:ellipsis; overflow: hidden; max-width:1px;">This cell has more content.This cell has more content.This cell has more content.This cell has more content.This cell has more content.This cell has more content.</td>
        <td style="white-space: nowrap;">Less content here.</td>
    </tr>
</table>

http://jsfiddle.net/7CURQ/

ladislav
fuente
99
Ugh Funciona muy bien, pero no tengo idea de por qué, lo que me pone nervioso :(
Shaun Rowan
¡Gracias! No hace exactamente lo que decía la pregunta (truncar todas las columnas de manera uniforme), pero el comportamiento de este código es lo que estaba buscando.
Sam
3
Además, tenga en cuenta que puede eliminar la <col>s en lugar de anteponer los anchos a los <td>estilos: jsfiddle.net/7CURQ/64
Sam
2
En realidad, esto parece estropear el tamaño dinámico de la columna de las columnas no truncadas. Parecen siempre encogerse al ancho mínimo.
Sam
38

¡Creo que tengo una solución que no es JavaScript! Mejor tarde que nunca, ¿cierto? Después de todo, esta es una excelente pregunta y Google está por todas partes. No quería conformarme con una solución de JavaScript porque encuentro que la leve fluctuación de las cosas que se mueven después de cargar la página es inaceptable.

Caracteristicas :

  • Sin javascript
  • Sin diseño fijo
  • Sin ponderación o trucos de ancho porcentual
  • Funciona con cualquier cantidad de columnas.
  • Generación simple del lado del servidor y actualización del lado del cliente (no es necesario realizar ningún cálculo)
  • Compatible con navegador cruzado

Cómo funciona : dentro de la celda de la tabla, coloque dos copias del contenido en dos elementos diferentes dentro de un elemento contenedor relativamente posicionado. El elemento espaciador está posicionado estáticamente y, como tal, afectará el ancho de las celdas de la tabla. Al permitir que el contenido de la celda espaciadora se ajuste, podemos obtener el ancho de "mejor ajuste" de las celdas de la tabla que estamos buscando. Esto también nos permite usar el elemento en posición absoluta para restringir el ancho del contenido visible al del padre relativamente posicionado.

Probado y trabajando en: IE8, IE9, IE10, Chrome, Firefox, Safari, Opera

Imágenes del resultado :

Anchos proporcionales agradables Bonito recorte proporcional

JSFiddle : http://jsfiddle.net/zAeA2/

Ejemplo de HTML / CSS :

<td>
    <!--Relative-positioned container-->
    <div class="container">
        <!--Visible-->
        <div class="content"><!--Content here--></div>
        <!--Hidden spacer-->
        <div class="spacer"><!--Content here--></div>
        <!--Keeps the container from collapsing without
            having to specify a height-->
        <span>&nbsp;</span>
     </div>
</td>

.container {
    position: relative;
}
.content {
    position: absolute;
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.spacer {
    height: 0;
    overflow: hidden;
}
Lucifer Sam
fuente
3
Si su contenido es una palabra muy larga sin espacios, esto no funciona, pero solo necesita agregar guiones al contenido en el espaciador con & shy; jsfiddle.net/zAeA2/160
Riccardo Casatta
2
¡Esto es bastante asombroso! Hice
Jayen
@Jayen Nice - Tal vez use en titlelugar de data-spacerobtener información sobre herramientas al pasar el mouse sobre :)
William George
@Jayen, acabo de probar el tuyo y no parece truncar la celda en el lado derecho, por lo que no cumple con el requisito de que las celdas se desborden de manera uniforme. Estoy usando Chrome 46.
Sam
@ Sam, sí, eso es correcto. mi ejemplo solo muestra que ambos tipos de celdas se pueden hacer sin duplicar contenido. No estaba tratando de responder la pregunta, simplemente mostrando otra forma. si cambias el HTML en mi ejemplo, funciona como quieras.
Jayen
24

Me he enfrentado al mismo desafío hace unos días. Parece que Lucifer Sam encontró la mejor solución.

Pero noté que debería duplicar el contenido en el elemento espaciador. Pensé que no era tan malo, pero también me gustaría aplicar una titleventana emergente para el texto recortado. Y significa que el texto largo aparecerá por tercera vez en mi código.

Aquí propongo acceder al titleatributo del :afterpseudo-elemento para generar un espaciador y mantener limpio el HTML.

Funciona en IE8 +, FF, Chrome, Safari, Opera

<table border="1">
  <tr>
    <td class="ellipsis_cell">
      <div title="This cells has more content">
        <span>This cells has more content</span>
      </div>
    </td>
    <td class="nowrap">Less content here</td>
  </tr>
</table>
.ellipsis_cell > div {
    position: relative;
    overflow: hidden;
    height: 1em;
}

/* visible content */
.ellipsis_cell > div > span {
    display: block;
    position: absolute; 
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1em;
}

/* spacer content */
.ellipsis_cell > div:after {
    content: attr(title);
    overflow: hidden;
    height: 0;
    display: block;
}

http://jsfiddle.net/feesler/HQU5J/

Henry Feesler
fuente
No podría estar más de acuerdo, genial!
Mikhail
mucho mejor que las otras soluciones de CSS porque funciona en ambos órdenes, es decir, si la celda de más contenido va después de la celda de menor contenido.
buggedcom
19

Si Javascript es aceptable, preparé una rutina rápida que podría usar como punto de partida. Intenta dinámicamente adaptar el ancho de las celdas utilizando el ancho interno de un tramo, en reacción a los eventos de cambio de tamaño de la ventana.

Actualmente se supone que cada celda normalmente obtiene el 50% del ancho de la fila, y colapsará la celda derecha para mantener la celda izquierda en su ancho máximo para evitar el desbordamiento. Podría implementar una lógica de equilibrio de ancho mucho más compleja, dependiendo de sus casos de uso. Espero que esto ayude:

Marcado para la fila que utilicé para probar:

<tr class="row">
    <td style="overflow: hidden; text-overflow: ellipsis">
    <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
    </td>
    <td style="overflow: hidden; text-overflow: ellipsis">
    <span>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span>
    </td>
</tr>

JQuery que conecta el evento de cambio de tamaño:

$(window).resize(function() {
    $('.row').each(function() {
        var row_width = $(this).width();
        var cols = $(this).find('td');
        var left = cols[0];
        var lcell_width = $(left).width();
        var lspan_width = $(left).find('span').width();
        var right = cols[1];
        var rcell_width = $(right).width();
        var rspan_width = $(right).find('span').width();

        if (lcell_width < lspan_width) {
            $(left).width(row_width - rcell_width);
        } else if (rcell_width > rspan_width) {
            $(left).width(row_width / 2);
        }
    });
});
samplebias
fuente
18

Hay una solución mucho más fácil y más elegante.

Dentro de la celda de la tabla a la que desea aplicar el truncamiento, simplemente incluya un contenedor div con css table-layout: fixed. Este contenedor ocupa todo el ancho de la celda de la tabla principal, por lo que incluso actúa de manera receptiva.

Asegúrese de aplicar el truncamiento a los elementos en la tabla.

Funciona desde IE8 +

<table>
  <tr>
    <td>
     <div class="truncate">
       <h1 class="truncated">I'm getting truncated because I'm way too long to fit</h1>
     </div>
    </td>
    <td class="some-width">
       I'm just text
    </td>
  </tr>
</table>

y css:

    .truncate {
      display: table;
      table-layout: fixed;
      width: 100%;
    }

    h1.truncated {
      overflow-x: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

aquí hay un Fiddle que funciona https://jsfiddle.net/d0xhz8tb/

satyavh
fuente
Esta solución requiere 2 elementos de nivel de bloque adicionales para lograr un efecto no estructural. Es posible configurar una celda de tabla para "mostrar: tabla", lo que le permite deshacerse de uno de los divs. jsfiddle.net/rza4hfcv No estoy seguro, qué debería pensar sobre esto. ¡Pero gracias por compartir tu solución!
armin
¿Experimentó algún problema con esa solución? Estoy pensando en usarlo en un entorno profesional.
armin
@armin, intenta duplicar la celda que deseas truncar: no puedes poner más de una al lado de la otra.
DanielM
Sin embargo, no diría que esta es una solución final. Pierdes uno de los principales beneficios de una tabla: que las columnas cambien de tamaño según su contenido. Si configura cada columna de esta manera, todas tendrán el mismo ancho, sin importar la longitud de su contenido.
DanielM
@DanielM Puede ampliar la solución anidando aún más la tabla, como en los viejos días de diseño de tabla, pero ahora solo con css.
Armin
11

El problema es el 'diseño de tabla: fijo' que crea columnas de ancho fijo y espaciado uniformemente. Pero deshabilitar esta propiedad css matará el desbordamiento de texto porque la tabla se volverá lo más grande posible (y luego se notará que se desborda).

Lo siento, pero en este caso Fred no puede tener su pastel y comérselo ... a menos que el propietario le dé a Celldito menos espacio para trabajar, Fred no puede usar el suyo ...

Andre Haverdings
fuente
9

Podrías intentar "ponderar" ciertas columnas, como esta:

<table border="1" style="width: 100%;">
    <colgroup>
        <col width="80%" />
        <col width="20%" />
    </colgroup>
    <tr>
        <td>This cell has more content.</td>
        <td>Less content here.</td>
    </tr>
</table>

También puede probar algunos ajustes más interesantes, como usar columnas de 0% de ancho y usar alguna combinación de la white-spacepropiedad CSS.

<table border="1" style="width: 100%;">
    <colgroup>
        <col width="100%" />
        <col width="0%" />
    </colgroup>
    <tr>
        <td>This cell has more content.</td>
        <td style="white-space: nowrap;">Less content here.</td>
    </tr>
</table>

Tienes la idea.

Elliot Cameron
fuente
3

Sí, diría que thirtydot lo tiene, no hay forma de hacerlo a menos que use un método js. Estás hablando de un conjunto complejo de condiciones de representación que tendrás que definir. Por ejemplo, qué sucede cuando ambas celdas se están volviendo demasiado grandes para sus apartamentos, tendrá que decidir quién tiene prioridad o simplemente darles un porcentaje del área y si están demasiado ocupados, ambos ocuparán esa área y solo si uno tiene un espacio en blanco. estira las piernas en la otra celda, de cualquier manera no hay forma de hacerlo con css. Aunque hay algunas cosas bastante funky que la gente hace con CSS que no he pensado. Aunque realmente dudo que puedas hacer esto.

usuario648116
fuente
3

Al igual que la respuesta samplebias, una vez más, si Javascript es una respuesta aceptable, hice un complemento jQuery específicamente para este propósito: https://github.com/marcogrcr/jquery-tableoverflow

Para usar el complemento simplemente escriba

$('selector').tableoverflow();

Ejemplo completo: http://jsfiddle.net/Cw7TD/3/embedded/result/

Ediciones:

  • Arreglo en jsfiddle para la compatibilidad con IE.
  • Arreglo en jsfiddle para una mejor compatibilidad del navegador (Chrome, Firefox, IE8 +).
Marco
fuente
3

Use algún truco css, parece que display: table-column;puede venir a rescatarlo:

<div class="myTable">
    <div class="flexibleCell">A very long piece of content in first cell, long enough that it would normally wrap into multiple lines.</div>
    <div class="staticCell">Less content</div>
</div>

.myTable {
    display: table;
    width: 100%;
}

.myTable:before {
    display: table-column;
    width: 100%;
    content: '';
}

.flexibleCell {
    display: table-cell;
    max-width:1px;
    white-space: nowrap;
    text-overflow:ellipsis;
    overflow: hidden;
}

.staticCell {
    white-space: nowrap;
}

JSFiddle: http://jsfiddle.net/blai/7u59asyp/

blai
fuente
Gran solución! ¡Gracias!
Valeriu92
Se veía bastante bien hasta que agregué una celda estática antes de una celda flexible: jsfiddle.net/7u59asyp/5
Sam
este es el único que funcionó para mí, aunque no perfectamente, ya que tengo 4 columnas con diferentes tamaños de contenido esperados
alzada el
3

Simplemente agregue las siguientes reglas a su td:

overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
// These ones do the trick
width: 100%;
max-width: 0;

Ejemplo:

table {
  width: 100%
}

td {
  white-space: nowrap;
}

.td-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
  max-width: 0;
}
<table border="1">
  <tr>
    <td>content</td>
    <td class="td-truncate">long contenttttttt ttttttttt ttttttttttttttttttttttt tttttttttttttttttttttt ttt tttt ttttt ttttttt tttttttttttt ttttttttttttttttttttttttt</td>
    <td>other content</td>
  </tr>
</table>

PD: si desea establecer un ancho personalizado para otra tdpropiedad de uso min-width.

Alexandre Annic
fuente
El problema con esto es que, por defecto, las columnas de la tabla consumen espacio proporcionalmente. Si el contenido de una fila es más largo que el de otra, asignará más ancho. Sin embargo, esta técnica divide uniformemente el espacio. ¿Hay alguna solución?
Malik Brahimi
2

Esta pregunta aparece en Google, así que en mi caso, utilicé el fragmento css de https://css-tricks.com/snippets/css/truncate-string-with-ellipsis/ pero aplicarlo al td NO dio El resultado deseado.

Tuve que agregar una etiqueta div alrededor del texto en el td y los puntos suspensivos finalmente funcionaron.

Código HTML abreviado;

<table style="width:100%">
 <tr>
    <td><div class='truncate'>Some Long Text Here</div></td>
 </tr>
</table>

CSS abreviado;

.truncate { width: 300px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
MarcoZen
fuente
0

Compruebe si "nowrap" resuelve el problema hasta cierto punto. Nota: nowrap no es compatible con HTML5

<table border="1" style="width: 100%; white-space: nowrap; table-layout: fixed;">
<tr>
    <td style="overflow: hidden; text-overflow: ellipsis;" nowrap >This cells has more content  </td>
    <td style="overflow: hidden; text-overflow: ellipsis;" nowrap >Less content here has more content</td>
</tr>

amlan
fuente
white-space: nowraptiene el mismo efecto que el nowrapatributo (y lo estoy usando en el ejemplo). Agregarlo aquí no cambia nada, por lo que puedo decir.
s4y
0

puede establecer el ancho de la celda derecha al mínimo del ancho requerido, luego aplicar overflow-hidden + text-overflow al interior de la celda izquierda, pero Firefox tiene errores aquí ...

aunque, parece, flexbox puede ayudar

4esn0k
fuente
0

He estado trabajando recientemente en eso. Echa un vistazo a esta prueba jsFiddle , pruébalo tú mismo cambiando el ancho de la tabla base para verificar el comportamiento).

La solución es incrustar una tabla en otra:

<table style="width: 200px;border:0;border-collapse:collapse">
    <tbody>
        <tr>
            <td style="width: 100%;">
                <table style="width: 100%;border:0;border-collapse:collapse">
                    <tbody>
                        <tr>
                            <td>
                                <div style="position: relative;overflow:hidden">
                                    <p>&nbsp;</p>
                                    <p style="overflow:hidden;text-overflow: ellipsis;position: absolute; top: 0pt; left: 0pt;width:100%">This cells has more content</p>
                                </div>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="white-space:nowrap">Less content here</td>
        </tr>
    </tbody>
</table>

¿Fred ahora está contento con la expansión de Celldito?

IG Pascual
fuente
Perdón por la falta de respuesta! No puedo ver cómo esto se comporta de manera diferente desde una sola tabla. Cuando veo el violín en Chrome o Firefox, se ve exactamente como la segunda captura de pantalla de la pregunta. ¿Me estoy perdiendo de algo?
s4y
Lo siento, el enlace no fue el que publiqué. En realidad es este jsfiddle.net/VSZPV/2 . Cambie el texto de ambas celdas y el ancho de la tabla principal para probar. Espero que sea lo que estabas buscando ...
IG Pascual
0

No sé si esto ayudará a alguien, pero resolví un problema similar especificando tamaños de ancho específicos en porcentaje para cada columna. Obviamente, esto funcionaría mejor si cada columna tiene contenido con un ancho que no varía demasiado.

DKO
fuente
-1

Tuve el mismo problema, pero necesitaba mostrar varias líneas (donde text-overflow: ellipsis;falla). Lo resuelvo usando un textareainterior ay TDluego lo estilizo para que se comporte como una celda de tabla.

    textarea {
        margin: 0;
        padding: 0;
        width: 100%;
        border: none;
        resize: none;

        /* Remove blinking cursor (text caret) */
        color: transparent;
        display: inline-block;
        text-shadow: 0 0 0 black; /* text color is set to transparent so use text shadow to draw the text */
        &:focus {
            outline: none;
        }
    }
Nicero
fuente
-2

Dado que 'table-layout: fixed' es el requisito de diseño esencial, que esto crea columnas no ajustables espaciadas uniformemente, pero que necesita hacer celdas de diferentes porcentajes de ancho, ¿tal vez establecer el 'colspan' de sus celdas en un múltiplo?

Por ejemplo, usando un ancho total de 100 para cálculos de porcentajes fáciles y diciendo que necesita una celda del 80% y otra del 20%, considere:

<TABLE width=100% style="table-layout:fixed;white-space:nowrap;overflow:hidden;">
     <tr>
          <td colspan=100>
               text across entire width of table
          </td>
     <tr>
          <td colspan=80>
               text in lefthand bigger cell
          </td>
          <td colspan=20>
               text in righthand smaller cell
          </td>
</TABLE>

Por supuesto, para columnas de 80% y 20%, puede establecer el colspan de celda de ancho del 100% en 5, el 80% en 4 y el 20% en 1.

Siubear
fuente
1
Hola @Siubear. ¿Cómo es eso diferente de especificar un porcentaje de ancho en el tds?
s4y
Usar colspan de esa manera es una idea horrible. ¿Por qué no usar ancho en su lugar?
Percy