Menggunakan CSS, cara "rapat" menyelaraskan "A" ke bagian bawah / akhir dari "B" di mana "B" memiliki lebar dan pembungkus teks yang tidak diketahui

9

Saya memiliki tabel "sortable" di mana tajuk kolom yang saat ini disortir menampilkan ikon:

masukkan deskripsi gambar di sini

Ikon sortir akan ditampilkan di akhir teks (yaitu, kami mendukung LTR / RTL). Saya sedang menggunakan display:flex. Namun, jika lebar tabel menyusut dan teks tajuk kolom mulai membungkus, saya mengalami keadaan ambigu di mana tidak jelas kolom mana yang diurutkan:

masukkan deskripsi gambar di sini

Sebaliknya saya ingin memenuhi persyaratan berikut:

  1. Ikon selalu "erat" selaras dengan "ujung" dari baris teks terpanjang (bahkan jika sel / tombol pembungkus lebih luas).
  2. Ikon juga harus sejajar dengan baris terakhir dari teks.
  3. Ikon tidak boleh membungkus ke garis sendiri.
  4. Tombol harus ada dan harus merentang sel penuh. (Ini gaya dan markup internal dapat berubah sesuai kebutuhan.)
  5. CSS dan HTML hanya jika memungkinkan.
  6. Itu tidak bisa mengandalkan lebar kolom atau teks header yang diketahui / diatur.

Sebagai contoh:

masukkan deskripsi gambar di sini

Saya telah bereksperimen dengan sekelompok kombinasi yang berbeda dari display: inline/inline-block/flex/grid, position, ::before/::after, dan bahkan float(!) Tapi tidak bisa mendapatkan perilaku yang diinginkan. Ini kode saya saat ini yang menunjukkan masalah:

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

Ada ide tentang bagaimana mencapai UI ini? Ini mungkin tidak ada hubungannya dengan hal-hal tabel atau tombol. Benar-benar saya perlu Thing A"erat" bawah / ujung selaras ke Thing B(dari lebar yang fleksibel dan yang dapat membungkus teks) tetapi Thing Atidak dapat membungkus ke baris sendiri.

Saya sudah mencoba mengacaukan flexnilai - nilai tetapi kombinasi apa pun membuat pembungkus teks terlalu dini atau tidak cukup cepat.

robertwbradford
sumber
Saya mencoba untuk memperbaiki masalah Anda dengan css dan html Anda saat ini namun tombol dan elemen span digabungkan di mana sakit kepala jadi saya memutuskan untuk menggunakan font-mengagumkan dengan css dan html di sini adalah contoh harapan itu membantu
stan chacon
@stanchacon terima kasih telah melihatnya. Seharusnya saya sebutkan, tapi saya tidak akan memiliki kemewahan mengatur lebar kolom atau mengetahui apa yang akan menjadi teks header sebelumnya. Saya menambahkan # 6 ke persyaratan.
robertwbradford
1
@stanchacon ... dan saya bisa pergi untuk ribeye tentang sekarang :)
robertwbradford
@robertwbradford Apakah ini sudah ditangani? Atau Anda masih mencari solusi?
Furqan Rahamath
@MohammedFurqanRahamathM, ini belum dijawab. Masih mencari ...
robertwbradford

Jawaban:

1

Pikirkan Anda membutuhkan JS untuk ini. Inilah jawaban yang harus memenuhi semua persyaratan kecuali 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>

sol
sumber
1

Saya pikir tidak ada masalah sama sekali di sini kecuali ambiguitas visual. Inilah pengamatan saya.

  • Barang-barang sebenarnya terikat erat. Secara default elemen apa pun akan mengikuti yang lain kecuali ditentukan lain.
  • Kenapa ada spasi? Ada dua variasi di antaranya
    • Pertama: Jika teks tidak ada di dalam elemen pembungkus (keadaan di mana ia berada sekarang). Dalam skenario ini, karena tidak ada lebar yang disebutkan secara eksplisit, baik untuk teks maupun rentang, ada penetapan lebar otomatis dan teks berusaha untuk semua lebar kecuali lebar 1,25rem yang diambil oleh elemen span. Dan menurut dokumentasi w3c, aturan yang ada hanya untuk mengidentifikasi breakpoint pada string yang diberikan dan tidak spasi, karena pembenaran teks adalah masalah yang sama sekali berbeda. Silakan merujuk masalah ini untuk memahami bagaimana hal itu dilakukan, itu adalah pertanyaan pemrograman Dinamis standar yang dipelajari di perguruan tinggi. Jadi tentu saja jarak akan ada saat melakukan pembenaran dan harap ingat lebar yang tersedia, yang tidak akan runtuh oleh peramban.
    • Kedua: Jika teks berada di dalam elemen pembungkus , bisa berupa span, p, div dll. Dalam hal ini juga, penetapan lebar otomatis terjadi karena tidak ada lebar yang ditentukan secara eksplisit. Dan dalam hal ini, Anda benar-benar dapat melihat di elemen memeriksa bahwa elemen mencoba untuk menempati semua ruang kecuali lebar 1,25rem dari ikon semacam.

Begitu terikat erat , memang ada, hanya saja jarak dinamisnya yang menyebabkan ambiguitas visual.

Sekarang datang ke solusi, solusi terdekat yang bisa saya buat tanpa intervensi JavaScript , meskipun tidak sempurna, adalah,

  • Bungkus teks di dalam elemen, mungkin rentang
  • Batasi lebar teks ini dengan memberikan lebar maksimum:

    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
    }

Catatan: Ini text-align: centerhanya untuk mengurangi efek ruang yang hilang, kecuali Anda memiliki persyaratan ketat untuk tidak melakukannya.

Tolong beri tahu saya jika ini menjawab pertanyaan Anda.

Beginilah efeknya: masukkan deskripsi gambar di sini

Furqan Rahamath
sumber
Terima kasih balasannya. Untuk ini kami memiliki persyaratan untuk itu harus pada akhirnya.
robertwbradford
@robertwbradford Saya telah mengubah jawaban saya menjelaskan kemungkinan masalah yang Anda hadapi dan mengusulkan solusi. Tolong beri tahu saya jika ini menjawab pertanyaan Anda.
Furqan Rahamath
0

Saya pikir Anda hampir baik dan kehilangan (3) yang merupakan trik kecil. Gagasannya adalah membuat elemen ikon memiliki lebar sama dengan 0dan menonaktifkan spasi putih antara teks dan ikon sortir. Untuk ini saya menggunakan pembungkus tambahan untuk teks dan menghapus penggunaan flexbox.

Anda akan mengalami beberapa overflow tetapi itu tidak menjadi masalah karena Anda menerapkan padding. Anda juga dapat menambah padding-rightjika Anda mau

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

Temani Afif
sumber
Terima kasih balasannya. Beberapa poin bagus, tapi saya lihat itu tidak memenuhi "persyaratan 1" di mana panah harus disejajarkan dengan akhir baris teks terpanjang. Dalam hal "Warna Favorit", ketika "Warna" membungkus ke baris kedua, ikon harus sejajar secara horizontal dengan ujung "Favorit" seperti yang ditunjukkan pada tangkapan layar terakhir.
robertwbradford
1
@robertwbradford ah tidak mengerti seperti itu .. Saya pikir itu harus ketat dengan yang terakhir. Saya pikir Anda kurang beruntung untuk persyaratan ini ...
Temani Afif
0

jika judul thead Anda tidak dinamis maka saya telah memperbaiki sangat mudah.

untuk ini, Anda harus meletakkan kata terakhir dari judul dan ikon svg dalam rentang waktu bersamaan

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

hapus display: flex dari .button class dan beri style display: inline-block ke span yang ditambahkan

karena span menjadi inline-block ikon svg tidak akan pernah berada di baris terpisah. setidaknya akan ada satu kata di depannya

Shirish Maharjan
sumber
Terima kasih atas balasannya. Saya sedang membangun ini sebagai komponen, sehingga teks judul akan dinamis :(
robertwbradford
Anda dapat menggunakan Js untuk menempatkan kata terakhir dalam rentang. Seharusnya tidak terlalu sulit
Shirish Maharjan
0

Anda dapat mencoba seperti ini:

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

Semoga jawaban ini akan membantu Anda. Saya tidak membuat css untuk tampilan seluler!

Krishna Savani
sumber