Saya telah membuat kode skrip (dengan bantuan pengguna di sini) yang memungkinkan saya untuk memperluas div yang dipilih dan membuat div lain berperilaku sesuai dengan peregangan yang sama agar sesuai dengan ruang yang tersisa (kecuali yang pertama yang lebarnya diperbaiki).
Dan inilah gambar yang ingin saya capai:
Untuk itu saya menggunakan flex dan transisi.
Ini bekerja dengan baik, tetapi skrip jQuery menentukan nilai peregangan "400%" (yang bagus untuk pengujian).
Sekarang saya ingin div yang dipilih untuk memperluas / menyusut agar sesuai dengan konten, bukan nilai tetap "400%".
Saya tidak tahu bagaimana saya bisa melakukan itu.
Apa itu mungkin ?
Saya mencoba mengkloning div, menyesuaikannya dengan konten, mendapatkan nilainya dan kemudian menggunakan nilai ini untuk transisi NAMUN ini berarti saya memiliki lebar awal dalam persentase tetapi nilai target dalam piksel. Itu tidak berhasil.
Dan jika saya mengonversi nilai piksel dalam persentase, maka hasilnya tidak persis sesuai dengan konten untuk alasan apa pun.
Dalam semua kasus, ini tampaknya sedikit cara yang rumit untuk mencapai apa yang saya inginkan.
Apakah tidak ada properti fleksibel yang dapat ditransisikan agar sesuai dengan konten div yang dipilih?
Berikut adalah kode ( diedit / disederhanakan karena untuk dibaca lebih baik ):
var expanded = '';
$(document).on("click", ".div:not(:first-child)", function(e) {
var thisInd =$(this).index();
if(expanded != thisInd) {
//fit clicked fluid div to its content and reset the other fluid divs
$(this).css("width", "400%");
$('.div').not(':first').not(this).css("width", "100%");
expanded = thisInd;
} else {
//reset all fluid divs
$('.div').not(':first').css("width", "100%");
expanded = '';
}
});
.wrapper {
overflow: hidden;
width: 100%;
margin-top: 20px;
border: 1px solid black;
display: flex;
justify-content: flex-start;
}
.div {
overflow: hidden;
white-space: nowrap;
border-right: 1px solid black;
text-align:center;
}
.div:first-child {
min-width: 36px;
background: #999;
}
.div:not(:first-child) {
width: 100%;
transition: width 1s;
}
.div:not(:first-child) span {
background: #ddd;
}
.div:last-child {
border-right: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Click on the div you want to fit/reset (except the first div)
<div class="wrapper">
<div class="div"><span>Fixed</span></div>
<div class="div"><span>Fluid (long long long long long text)</span></div>
<div class="div"><span>Fluid</span></div>
<div class="div"><span>Fluid</span></div>
</div>
Ini jsfiddle:
https://jsfiddle.net/zajsLrxp/1/
EDIT: Ini adalah solusi kerja saya dengan bantuan Anda semua (ukuran diperbarui pada ukuran jendela + jumlah divs dan lebar kolom pertama dihitung secara dinamis):
var tableWidth;
var expanded = '';
var fixedDivWidth = 0;
var flexPercentage = 100/($('.column').length-1);
$(document).ready(function() {
// Set width of first fixed column
$('.column:first-child .cell .fit').each(function() {
var tempFixedDivWidth = $(this)[0].getBoundingClientRect().width;
if( tempFixedDivWidth > fixedDivWidth ){fixedDivWidth = tempFixedDivWidth;}
});
$('.column:first-child' ).css('min-width',fixedDivWidth+'px')
//Reset all fluid columns
$('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')
})
$(window).resize( function() {
//Reset all fluid columns
$('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')
expanded = '';
})
$(document).on("click", ".column:not(:first-child)", function(e) {
var thisInd =$(this).index();
// if first click on a fluid column
if(expanded != thisInd)
{
var fitDivWidth=0;
// Set width of selected fluid column
$(this).find('.fit').each(function() {
var c = $(this)[0].getBoundingClientRect().width;
if( c > fitDivWidth ){fitDivWidth = c;}
});
tableWidth = $('.mainTable')[0].getBoundingClientRect().width;
$(this).css('flex','0 0 '+ 100/(tableWidth/fitDivWidth) +'%')
// Use remaining space equally for all other fluid column
$('.column').not(':first').not(this).css('flex','1 1 '+flexPercentage+'%')
expanded = thisInd;
}
// if second click on a fluid column
else
{
//Reset all fluid columns
$('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')
expanded = '';
}
});
body{
font-family: 'Arial';
font-size: 12px;
padding: 20px;
}
.mainTable {
overflow: hidden;
width: 100%;
border: 1px solid black;
display: flex;
margin-top : 20px;
}
.cell{
height: 32px;
border-top: 1px solid black;
white-space: nowrap;
}
.cell:first-child{
background: #ccc;
border-top: none;
}
.column {
border-right: 1px solid black;
transition: flex 0.4s;
overflow: hidden;
line-height: 32px;
text-align: center;
}
.column:first-child {
background: #ccc;
}
.column:last-child {
border-right: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="text">Click on the header div you want to fit/reset (except the first one which is fixed)</span>
<div class="mainTable">
<div class="column">
<div class="cell"><span class="fit">Propriété</span></div>
<div class="cell"><span class="fit">Artisan 45</span></div>
<div class="cell"><span class="fit">Waterloo 528</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Adresse</span></div>
<div class="cell"><span class="fit">Rue du puit n° 45 (E2)</span></div>
<div class="cell"><span class="fit">Chaussée de Waterloo n° 528 (E1)</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Commune</span></div>
<div class="cell"><span class="fit">Ixelles</span></div>
<div class="cell"><span class="fit">Watermael-Boitsfort</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Ville</span></div>
<div class="cell"><span class="fit">Marche-en-Famenne</span></div>
<div class="cell"><span class="fit">Bruxelles</span></div>
</div>
<div class="column">
<div class="cell"><span class="fit">Surface</span></div>
<div class="cell"><span class="fit">120 m<sup>2</sup></span></div>
<div class="cell"><span class="fit">350 m<sup>2</sup></span></div>
</div>
</div>
Dan di sini adalah contoh yang lengkap di tempat kerja (gaya + padding + lebih banyak data):
https://jsfiddle.net/zrqLowx0/2/
Terima kasih semua !
sumber
Jawaban:
Dimungkinkan untuk menyelesaikannya menggunakan
max-width
dancalc()
.Pertama, ganti
width: 100%
denganflex: 1
untuk divs di CSS, sehingga mereka akan tumbuh, yang lebih baik dalam hal ini. Selain itu, gunakan transisi untukmax-width
.Sekarang, kita harus menyimpan beberapa nilai yang relevan:
divsLength
variabel) - 3 dalam hal ini.extraSpace
variabel) - 39px dalam kasus ini.Dengan 2 variabel tersebut, kita dapat menetapkan default
max-width
(defaultMaxWidth
variabel) untuk semua divs, serta menggunakannya nanti. Itulah sebabnya mereka disimpan secara global.The
defaultMaxWidth
adalahcalc((100% - extraSpace)/divsLength)
.Sekarang, mari masuk ke fungsi klik:
Untuk memperluas div, lebar teks target akan disimpan dalam variabel yang dipanggil
textWidth
dan itu akan diterapkan ke div saatmax-width.
digunakan.getBoundingClientRect().width
(karena mengembalikan nilai floating-point).Untuk div yang tersisa, dibuat
calc()
untukmax-width
yang akan diterapkan pada mereka.Ini adalah:
calc(100% - textWidth - extraScape)/(divsLength - 1)
.Hasil yang dihitung adalah lebar yang seharusnya setiap div tersisa.
Ketika mengklik div diperluas, yaitu, untuk kembali ke normal, standarnya
max-width
diterapkan lagi ke semua.div
elemen.Pendekatan ini berperilaku dinamis dan harus bekerja pada resolusi apa pun.
Satu-satunya nilai yang Anda butuhkan untuk hard code adalah
extraSpace
variabel.sumber
Anda harus berurusan dengan fungsi lebar atau kalk. Flexbox tentu punya solusi.
Untuk membuat semua div sama (bukan yang pertama) kami gunakan
flex: 1 1 auto
.Tetapkan aturan fleksibel untuk div normal dan div terpilih.
transition: flex 1s;
adalah temanmu Untuk yang terpilih, kita tidak perlu pertumbuhan fleksibel, jadi kita gunakanflex: 0 0 auto
;Tambahkan kelas yang dipilih setiap kali ketika pengguna mengklik sebuah div. Anda juga dapat menggunakan sakelar untuk klik kedua sehingga Anda dapat menyimpan item yang dipilih di peta dan Anda dapat menampilkan beberapa item yang dipilih (tidak dengan contoh kode ini tentu saja).
https://jsfiddle.net/f3ao8xcj/
sumber
Flex transition: Stretch (or shrink) to fit content
adalah judul pertanyaan Anda dan jawaban ini adalah contoh sederhana bagaimana melakukannya. Adalah tanggung jawab Anda untuk menemukan solusi untuk kasus Anda.Setelah beberapa versi uji coba, ini tampaknya menjadi solusi terpendek dan paling lurus bagi saya.
Semua yang pada dasarnya perlu dilakukan yaitu memiliki flexbox meregangkan
<div>
elemen untuk batas mereka secara default, tapi ketika<span>
diklik, kendala peregangan dari<div>
untuk<span>
lebar ...kode semu:
when <span> clicked and already toggled then <div> max-width = 100%, reset <span> toggle state
otherwise <div> max-width = <span> width, set <span> toggle state
Saya telah membagi CSS menjadi bagian 'mekanisme yang relevan' dan 'eye-candy only' untuk memudahkan membaca (dan kode recyling).
Kode ini banyak dikomentari, jadi tidak banyak teks di sini ...
Quirk Entah bagaimana ada penundaan tambahan
transition
saat beralihdiv
darimax-width: 100%
kemax-width = span width
. Saya telah memeriksa perilaku ini di Chrome, Edge, IE11 dan Firefox (semua W10) dan semua tampaknya memiliki kekhasan ini. Entah beberapa recalc internal browser berlangsung, atau mungkintransition
waktu digunakan dua kali ('terasa seperti'). Begitu juga sebaliknya, cukup aneh, tidak ada penundaan tambahan.Namun, dengan waktu transisi yang singkat (mis. 150 ms, seperti yang saya gunakan sekarang) keterlambatan tambahan ini tidak / hampir tidak terlihat. (Bagus untuk pertanyaan SO lainnya ...)
Tampilkan cuplikan kode
MEMPERBARUI
Versi baru yang mengatur ulang semua lainnya
<div>
. Saya benar-benar benci kegelisahan, tapi itu karena peregangan dantransition
nilai Flexbox . Tanpatransition
ada lompatan yang terlihat. Anda perlu mencoba apa yang cocok untuk Anda.Saya hanya menambahkan
document.querySelectorAll()
kode javascript.Tampilkan cuplikan kode
sumber