Використовуючи CSS, як "щільно" вирівняти "A" внизу / кінці "B", де "B" має невідому ширину та обгортання тексту


9

У мене є "сортована" таблиця, де в заголовку поточно відсортованого стовпця відображається значок:

введіть тут опис зображення

Піктограма сортування повинна відображатися в кінці тексту (тобто ми підтримуємо LTR / RTL). Я зараз використовую display:flex. Однак якщо ширина таблиці зменшується і текст заголовка стовпця починає загортатись, я стикаюся з неоднозначними станами, де не зрозуміло, який стовпець відсортовано:

введіть тут опис зображення

Натомість я хотів би відповідати наступним вимогам:

  1. Піктограма завжди повинна бути «щільно» вирівняна з «кінцем» найдовшого рядка тексту (навіть якщо комірка / кнопка, що обгортає, ширше).
  2. Піктограма також повинна бути вирівняна внизу з останнім рядком тексту.
  3. Ікона ніколи не повинна обертатися на власну лінію.
  4. Кнопка повинна бути присутнім і повинна охоплювати всю ширину комірки. (Внутрішній стиль та розмітка можуть змінюватися за потреби.)
  5. CSS та HTML, лише якщо це можливо.
  6. Він не може покладатися на відому / задану ширину стовпця або текст заголовка.

Наприклад:

введіть тут опис зображення

Я експериментував з купою різних комбінацій display: inline/inline-block/flex/grid, position, ::before/::afterі навіть float(!) , Але не може отримати бажане поведінку. Ось мій поточний код, що демонструє проблему:

.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>

Будь-які ідеї, як досягти цього інтерфейсу? Це, мабуть, мало стосується таблиці або кнопкових матеріалів. Дійсно, мені потрібно Thing A«щільно» вирівняти низ / кінець Thing B(гнучкої ширини і, який може мати загорнутий текст), але я Thing Aне можу перегорнутись на власну лінію.

Я спробував возитися з flex значеннями, але будь-яка комбінація або перетворює текст передчасно, або недостатньо скоро.


Я спробував виправити свою проблему з вашим поточним css та html, однак кнопка та елемент "span" поєднуються там, де болить
голова,

Дякуємо @stanchacon за огляд. Я повинен був би згадати, але мені не вистачить розкоші встановлювати ширину стовпців або знати, який текст заголовка буде достроково. Я додав №6 до вимог.
robertwbradford

1
@stanchacon ... і я можу зараз поїхати на
рібі

@robertwbradford Це вже вирішено? Або ти все ще шукаєш рішення?
Фуркан Рагамат

@MohammedFurqanRahamathM, на це ще не відповіли. Ще дивлячись ...
robertwbradford

Відповіді:


1

Подумайте, вам потрібен JS для цього. Ось відповідь, яка повинна відповідати всім умовам, крім 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

Я думаю, тут взагалі немає жодної проблеми, окрім візуальної неоднозначності. Ось мої спостереження.

  • Фактично предмети щільно пов'язані. За замовчуванням будь-який елемент буде слідувати іншому, якщо не вказано інше.
  • Чому існує інтервал? Існує дві варіанти
    • По-перше: Якщо текст не знаходиться всередині якогось обгорткового елемента (стан, у якому він знаходиться зараз). У цьому сценарії, оскільки немає чітко зазначеної ширини, як для тексту, так і для проміжку, існує автоматичне призначення ширини, і текст намагається на всю ширину, за винятком ширини 1,25 єм, яку займає елемент прольоту. Згідно з документацією на w3c, правила існують лише для визначення точок перерви в заданому рядку, а не для проміжків, тому що виправдання тексту - це зовсім інша проблема. Будь ласка, зверніться до цієї проблеми, щоб зрозуміти, як це робиться, його стандартне питання щодо динамічного програмування, вивчене в коледжі. Тому, звичайно, інтервал буде існувати під час обгрунтування, і пам’ятайте про наявну ширину, яку браузер не збирається згортати.
    • По-друге: Якщо текст знаходиться всередині обгорткового елемента , він може бути span, p, div тощо. У цьому випадку також відбувається автоматичне призначення ширини, оскільки чітко не вказана ширина. І в цьому випадку ви можете побачити в елементі огляду, що елемент намагається зайняти весь простір, за винятком ширини піктограми сортування 1,25 єм.

Настільки жорстке обмеження існує, саме його динамічний інтервал викликає візуальну неоднозначність.

Зараз, підходячи до рішення, найближче рішення, яке я міг би запропонувати без втручання JavaScript , хоча і не ідеальне,

  • Оберніть текст всередині елемента, можливо, проміжок
  • Обмежте ширину цього тексту, вказавши максимальну ширину:

    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
    }

Примітка:text-align: center полягає лише в тому, щоб зменшити ефект пропущеного місця, якщо ви не маєте суворої вимоги цього не робити.

Будь ласка, дайте мені знати, якщо це стосується вашого питання.

Ось як виглядав би ефект: введіть тут опис зображення


Дякую за відповідь. Для цього у нас є вимога, щоб вона була наприкінці.
robertwbradford

@robertwbradford Я змінив свою відповідь, пояснюючи можливу проблему, з якою ви стикаєтесь, і запропонував її рішення. Будь ласка, повідомте мене, чи відповідає це на ваше запитання.
Фуркан Рагамат

0

Я думаю, ти майже хороший і пропускаєш (3), що трохи трюк. Ідея полягає в тому, щоб зробити елемент піктограми шириною рівним 0та відключити пробіл між текстом та піктограмою сортування. Для цього я використовував додаткову обгортку для тексту і видаляв використання flexbox.

У вас буде деякий перелив, але це не проблема, оскільки ви застосовуєте прокладки. Ви також можете збільшитиpadding-right якщо хочете

.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>


Дякую за відповідь. Деякі хороші моменти, але я бачу, що він не відповідає "вимозі 1", коли стрілку потрібно вирівняти в кінці найдовшого рядка тексту. У разі "Улюбленого кольору", коли "Колір" переходить на другий рядок, значок повинен горизонтально вирівнюватися в кінці "Улюбленого", як показано на останньому екрані екрана.
robertwbradford

1
@robertwbradford ах не зрозумів це так .. Я думав, що це має бути тісно з останнім. Я думаю, вам не пощастило з цією вимогою ...
Темані Афіф

0

якщо ваша назва thead не динамічна, то у мене дуже легко виправити.

для цього вам доведеться з'єднати останнє слово заголовка та значок svg разом

наприклад: -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>

видалити дисплей: згинати з класу

через те, що проліт є вбудованим-блоком, значок SVG ніколи не буде в окремій лінії. перед нею буде хоча б одне слово


Дякую за відповідь Я будую це як компонент, тому текст заголовку буде динамічним :(
robertwbradford

Ви можете використовувати Js, щоб передати останнє слово в проміжок часу. Це не повинно бути важким
Ширіш Махарджан

0

Ви можете спробувати так:

<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>

Сподіваюсь, ця відповідь допоможе вам. Я не зробив css для перегляду для мобільних пристроїв!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.