Usando CSS, come "strettamente" allineare "A" alla fine / fine di "B" dove "B" ha larghezza sconosciuta e avvolgimento del testo


9

Ho una tabella "ordinabile" in cui l'intestazione della colonna attualmente ordinata visualizza un'icona:

inserisci qui la descrizione dell'immagine

L'icona di ordinamento deve essere visualizzata alla fine del testo (ovvero, stiamo supportando LTR / RTL). Attualmente sto usando display:flex. Tuttavia, se la larghezza della tabella si riduce e il testo dell'intestazione della colonna inizia a scorrere, corro in stati ambigui in cui non è chiaro quale colonna sia ordinata:

inserisci qui la descrizione dell'immagine

Vorrei invece soddisfare i seguenti requisiti:

  1. L'icona è sempre allineata "strettamente" con la "fine" della riga di testo più lunga (anche se la cella / il pulsante di avvolgimento sono più larghi).
  2. L'icona dovrebbe anche essere allineata in basso con l'ultima riga di testo.
  3. L'icona non dovrebbe mai avvolgersi su una linea a sé stante.
  4. Il pulsante deve essere presente e deve estendersi per l'intera larghezza della cella. (Lo stile e il markup interni possono cambiare in base alle esigenze.)
  5. CSS e HTML solo se possibile.
  6. Non può fare affidamento su larghezze di colonna note / impostate o sul testo dell'intestazione.

Per esempio:

inserisci qui la descrizione dell'immagine

Ho avuto modo di sperimentare con un mazzo di diverse combinazioni di display: inline/inline-block/flex/grid, position, ::before/::aftere persino float(!), Ma non riesco a ottenere il comportamento desiderato. Ecco il mio codice attuale che dimostra il problema:

.table {
  border-collapse: collapse;
  width: 100%;
}

.thead {
  border-bottom: 3px solid #d0d3d3;
}

.thead .tr {
  vertical-align: bottom;
}

.button {
  padding: 1rem;
  text-align: start;
  font-family: Arial, "noto sans", sans-serif;
  font-size: 0.875rem;
  border: 0;
  background-color: transparent;
  width: 100%;
  display: flex;
  align-items: flex-end;
  font-weight: bold;
  line-height: 1.4;
}

.sort {
  width: 1.25rem;
  height: 1.25rem;
}
<table class="table">
  <thead class="thead">
    <tr class="tr">
      <th class="th">
        <button class="button">
          Age
          <span class="sort"></span>
         </button>
      </th>
      <th class="th">
        <button class="button">
          Favorite Food
          <span class="sort"></span>
        </button>
      </th>
      <th class="th" aria-sort="ascending">
        <button class="button">
          Favorite Color
          <span class="sort">
            <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" role="presentation" style="width: 1.25rem; height: 1.25rem;"> <path d="M11.4709 4.2136C11.7638 3.92071 12.2386 3.92071 12.5315 4.2136L17.1277 8.8098C17.4206 9.10269 17.4206 9.57756 17.1277 9.87046C16.8348 10.1633 16.3599 10.1633 16.0671 9.87046L12.7512 6.55459V19.25C12.7512 19.6642 12.4154 20 12.0012 20C11.587 20 11.2512 19.6642 11.2512 19.25V6.55459L7.93533 9.87046C7.64244 10.1633 7.16756 10.1633 6.87467 9.87046C6.58178 9.57756 6.58178 9.10269 6.87467 8.8098L11.4709 4.2136Z"> </path></svg>
          </span>
        </button>
      </th>
      <th class="th">
        <button class="button">
          Likes Neil Diamond?
          <span class="sort"></span>
        </button>
      </th>
    </tr>
  </thead>
</table>

Qualche idea su come realizzare questa UI? Questo probabilmente ha poco a che fare con la roba da tavolo o pulsante. Ho davvero bisogno che la parte Thing Ainferiore / fine "strettamente" sia allineata a Thing B(di una larghezza flessibile e che possa avere il testo a capo ) ma Thing Anon riesca ad andare a capo su una linea a sé stante.

Ho provato a fare confusione con i flexvalori, ma qualsiasi combinazione rende il testo prematuramente prematuro o non abbastanza presto.


Ho provato a risolvere il tuo problema con i tuoi CSS e HTML attuali, tuttavia il pulsante e l'elemento span si sono combinati in un mal di testa, quindi ho deciso di usare font-awesome con CSS e HTML qui è un esempio di speranza che aiuti
stan chacon

@stanchacon grazie per dare un'occhiata. Avrei dovuto menzionarlo, ma non avrò il lusso di impostare le larghezze delle colonne o di sapere in anticipo quale sarà il testo dell'intestazione. Ho aggiunto il numero 6 ai requisiti.
robertwbradford,

1
@stanchacon ... e potrei andare per un ribeye proprio ora :)
robertwbradford

@robertwbradford È già stato affrontato? O stai ancora cercando una soluzione?
Furqan Rahamath,

@MohammedFurqanRahamathM, questa non ha ancora ricevuto risposta. Ancora cercando ...
robertwbradford l'

Risposte:


1

Pensi di aver bisogno di JS per questo. Ecco una risposta che dovrebbe soddisfare tutte le condizioni tranne 5.

const debounce = fn => {
  let frame;

  return (...params) => {
    if (frame) {
      cancelAnimationFrame(frame);
    }
    frame = requestAnimationFrame(() => {
      fn(...params);
    });
  };
};

const text = [...document.querySelectorAll(".text")];
const iconWidth = "1.25rem";

const positionIcon = () => {
  if (!text) return;
  
  text.forEach(t => {
    const width = t.getBoundingClientRect().width;

    const icon = t.nextElementSibling;
    if (!icon) return;
    
    icon.style.left = `calc(${width}px + ${iconWidth})`;
  });
};

positionIcon();
window.addEventListener("resize", debounce(positionIcon));
.table {
  border-collapse: collapse;
  width: 100%;
}

.thead {
  border-bottom: 3px solid #d0d3d3;
}

.thead .tr {
  vertical-align: bottom;
}

.button {
  padding: 1rem;
  text-align: start;
  font-family: Arial, "noto sans", sans-serif;
  font-size: 0.875rem;
  border: 0;
  background-color: transparent;
  width: 100%;
  font-weight: bold;
  line-height: 1.4;
  position: relative;
}

.sort {
  width: 1.25rem;
  height: 1.25rem;
  position: absolute;
  bottom: 1rem;
  left: 100%; /* no js fallback */
}

.sort svg {
  height: 1.25rem;
  width: 1.25rem;
}
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
   <svg id="arrow" viewBox="0 0 24 24" role="presentation"> <path d="M11.4709 4.2136C11.7638 3.92071 12.2386 3.92071 12.5315 4.2136L17.1277 8.8098C17.4206 9.10269 17.4206 9.57756 17.1277 9.87046C16.8348 10.1633 16.3599 10.1633 16.0671 9.87046L12.7512 6.55459V19.25C12.7512 19.6642 12.4154 20 12.0012 20C11.587 20 11.2512 19.6642 11.2512 19.25V6.55459L7.93533 9.87046C7.64244 10.1633 7.16756 10.1633 6.87467 9.87046C6.58178 9.57756 6.58178 9.10269 6.87467 8.8098L11.4709 4.2136Z"> </path></svg>
</svg>
<table class="table">
  <thead class="thead">
    <tr class="tr">
      <th class="th">
        <button class="button">
          <span class="text">Age</span>
          <span class="sort">
            <svg>
              <use xlink:href="#arrow">
            </svg>
          </span>
         </button>
      </th>
      <th class="th">
        <button class="button">
          <span class="text">Favourite Food</span>
          <span class="sort">
          <svg>
              <use xlink:href="#arrow">
            </svg>
          </span>
        </button>
      </th>
      <th class="th" aria-sort="ascending">
        <button class="button">
          <span class="text">Favorite Color</span>
          <span class="sort">
            <svg>
              <use xlink:href="#arrow">
            </svg>
          </span>
        </button>
      </th>
      <th class="th">
        <button class="button">
          <span class="text">Likes Neil Diamond?</span>
          <span class="sort">
            <svg>
              <use xlink:href="#arrow">
            </svg>
          </span>
        </button>
      </th>
    </tr>
  </thead>
</table>


1

Penso che qui non ci siano problemi se non l'ambiguità visiva. Ecco le mie osservazioni

  • Gli articoli infatti sono strettamente legati. Per impostazione predefinita, qualsiasi elemento ne seguirebbe un altro se non diversamente specificato.
  • Perché c'è una spaziatura? Esistono due varianti di questi
    • Primo: se il testo non si trova all'interno di alcun elemento a capo (lo stato in cui si trova in questo momento). In questo scenario, poiché non viene esplicitamente menzionata alcuna larghezza, sia per il testo che per l'intervallo, esiste un'assegnazione automatica della larghezza e il testo sta provando a tutta la larghezza tranne la larghezza 1,25 che sta prendendo l'elemento span. E secondo la documentazione di w3c, le regole esistono solo per identificare i punti di interruzione su una data stringa e non la spaziatura, perché la giustificazione del testo è un problema completamente diverso. Si prega di fare riferimento a questo problema per capire come è fatto, è una domanda di programmazione dinamica standard studiata al college. Quindi, ovviamente, la spaziatura esisterà mentre si fa la giustificazione e si ricorda la larghezza disponibile, che il browser non sta per collassare.
    • Secondo: se il testo si trova all'interno di un elemento a capo , può essere span, p, div ecc. Anche in questo caso, l'assegnazione automatica della larghezza avviene poiché nessuna larghezza viene esplicitamente specificata. E in questo caso, puoi effettivamente vedere in inspect element che l'elemento cerca di occupare tutto lo spazio tranne la larghezza di 1,25rem dell'icona di ordinamento.

Esistono limiti così ristretti , è solo che la spaziatura dinamica sta causando l'ambiguità visiva.

Ora arrivando alla soluzione, la soluzione più vicina che potrei trovare senza l'intervento di JavaScript , anche se non perfetta, è,

  • Avvolgi il testo all'interno di un elemento, forse un arco
  • Limita la larghezza di questo testo assegnando una larghezza massima:

    button.button > span {
        max-width: 60%; // I saw this to be decent enough
        text-align: center; // This is to offset the visual effect of spacing
    }

Nota: L' text-align: centerè solo per ridurre l'effetto di spazio mancante, a meno che non hai requisito rigoroso di non andare con questo.

Per favore fatemi sapere se questo risponde alla vostra domanda.

Ecco come sarebbe l'effetto: inserisci qui la descrizione dell'immagine


Grazie per la risposta. Per questo abbiamo un requisito per essere alla fine.
robertwbradford,

@robertwbradford Ho cambiato la mia risposta spiegando il possibile problema che stai affrontando e ho proposto una soluzione. Per favore fatemi sapere se questo risponde alla vostra domanda.
Furqan Rahamath,

0

Penso che tu sia quasi bravo e ti manca il (3) che è un po 'ingannevole. Un'idea è di rendere l'elemento icona con una larghezza uguale 0e disabilitare qualsiasi spazio bianco tra il testo e l'icona di ordinamento. Per questo uso un wrapper aggiuntivo per il testo e ho rimosso l'uso di flexbox.

Avrai un po 'di overflow ma non è un problema dato che stai applicando il riempimento. Puoi anche aumentare il valore padding-rightse lo desideri

.table {
  border-collapse: collapse;
  width: 100%;
}

.thead {
  border-bottom: 3px solid #d0d3d3;
}

.thead .tr {
  vertical-align: bottom;
}

.button {
  padding: 1rem;
  text-align: start;
  font-family: Arial, "noto sans", sans-serif;
  font-size:0;
  border: 0;
  background-color: transparent;
  width: 100%;
  font-weight: bold;
  line-height: 1.4;
}
.button > span {
  font-size: 0.875rem;
}
.sort {
  width: 0;
  height: 1.25rem;
  display: inline-block;
  vertical-align: bottom;
}
<table class="table">
  <thead class="thead">
    <tr class="tr">
      <th class="th">
        <button class="button">
          <span>Age</span>
          <span class="sort"></span>
         </button>
      </th>
      <th class="th">
        <button class="button">
          <span>Favorite Food</span>
          <span class="sort"></span>
        </button>
      </th>
      <th class="th" aria-sort="ascending">
        <button class="button">
          <span>Favorite Color</span>
          <span class="sort">
            <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" role="presentation" style="width: 1.25rem; height: 1.25rem;"> <path d="M11.4709 4.2136C11.7638 3.92071 12.2386 3.92071 12.5315 4.2136L17.1277 8.8098C17.4206 9.10269 17.4206 9.57756 17.1277 9.87046C16.8348 10.1633 16.3599 10.1633 16.0671 9.87046L12.7512 6.55459V19.25C12.7512 19.6642 12.4154 20 12.0012 20C11.587 20 11.2512 19.6642 11.2512 19.25V6.55459L7.93533 9.87046C7.64244 10.1633 7.16756 10.1633 6.87467 9.87046C6.58178 9.57756 6.58178 9.10269 6.87467 8.8098L11.4709 4.2136Z"> </path></svg>
          </span>
        </button>
      </th>
      <th class="th">
        <button class="button">
          <span>Likes Neil Diamond?</span>
          <span class="sort"></span>
        </button>
      </th>
    </tr>
  </thead>
</table>


Grazie per la risposta. Alcuni punti positivi, ma sto vedendo che non soddisfa il "requisito 1" in cui la freccia dovrebbe essere allineata con la fine della riga di testo più lunga. Nel caso di "Colore preferito", quando "Colore" si sposta sulla seconda riga, l'icona dovrebbe allinearsi orizzontalmente con la fine di "Preferito", come mostrato nell'ultima schermata.
robertwbradford,

1
@robertwbradford ah non l'ho capito in quel modo .. Ho pensato che dovrebbe essere stretto con l'ultimo. Penso che tu sia sfortunato per questo requisito ...
Temani Afif

0

se il titolo del tuo thead non è dinamico, ho una soluzione molto semplice.

per questo dovrai mettere insieme l'ultima parola del titolo e l'icona svg

ad esempio: -html

<button>
 Long 

<span> title 
 <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" role="presentation" style="width: 1.25rem; height: 1.25rem;"> <path d="M11.4709 4.2136C11.7638 3.92071 12.2386 3.92071 12.5315 4.2136L17.1277 8.8098C17.4206 9.10269 17.4206 9.57756 17.1277 9.87046C16.8348 10.1633 16.3599 10.1633 16.0671 9.87046L12.7512 6.55459V19.25C12.7512 19.6642 12.4154 20 12.0012 20C11.587 20 11.2512 19.6642 11.2512 19.25V6.55459L7.93533 9.87046C7.64244 10.1633 7.16756 10.1633 6.87467 9.87046C6.58178 9.57756 6.58178 9.10269 6.87467 8.8098L11.4709 4.2136Z"> </path></svg>
</span>
</button>

rimuove display: flette dalla classe .button e dà stile display: blocco inline all'intervallo aggiunto

a causa del fatto che lo span è inline-block l'icona svg non sarà mai in linea separata. ci sarà almeno una parola davanti


Grazie per la risposta. Sto costruendo questo come componente, quindi il testo del titolo sarà dinamico :(
robertwbradford

Puoi usare Js per inserire l'ultima parola nell'intervallo. Non dovrebbe essere così difficile
Shirish Maharjan il

0

Potresti provare così:

<style>

.table {
  border-collapse: collapse;
  width: 100%;
}

.thead {
  border-bottom: 3px solid #d0d3d3;
}

.thead .tr {
  vertical-align: bottom;
}


.button {
  padding: 1rem;
  text-align: start;
  font-family: Arial, "noto sans", sans-serif;
  font-size: 0.875rem;
  border: 0;
  background-color: transparent;
    
 /* display: flex;
  align-items: flex-end;*/
  font-weight: bold;
  line-height: 1.4;
  float: left;
}
@media only screen and (min-width:502px)
{.button {
    width: calc(192px - 89px);
  }
  .button.food {
    width: calc(214px - 89px);
}
}

.sort {
  width: 1.25rem;
  height: 1.25rem;
  position: relative;
}
.sort svg {
  position: absolute;
}
</style>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <table class="table">
  <thead class="thead">
    <tr class="tr">
      <th class="th">
        <button class="button">
          Age
          <span class="sort"></span>
         </button>
      </th>
      <th class="th">
        <button class="button food">
          Favorite Food
          <span class="sort"></span>
        </button>
      </th>
      <th class="th" aria-sort="ascending">
        <button class="button">
          Favorite Color
          <span class="sort">
            <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" role="presentation" style="width: 1.25rem; height: 1.25rem;"> <path d="M11.4709 4.2136C11.7638 3.92071 12.2386 3.92071 12.5315 4.2136L17.1277 8.8098C17.4206 9.10269 17.4206 9.57756 17.1277 9.87046C16.8348 10.1633 16.3599 10.1633 16.0671 9.87046L12.7512 6.55459V19.25C12.7512 19.6642 12.4154 20 12.0012 20C11.587 20 11.2512 19.6642 11.2512 19.25V6.55459L7.93533 9.87046C7.64244 10.1633 7.16756 10.1633 6.87467 9.87046C6.58178 9.57756 6.58178 9.10269 6.87467 8.8098L11.4709 4.2136Z"> </path></svg>
          </span>
        </button>
      </th>
      <th class="th">
        <button class="button">
          Likes Neil Diamond?
          <span class="sort"></span>
        </button>
      </th>
    </tr>
  </thead>
</table>

Spero che questa risposta ti sia stata utile. Non ho creato CSS per la visualizzazione mobile!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.