The documentation is not very clear about all the grid options there.
I have this grid template in alpinejs styling it with tailwind:
<div x-show="multiple" class="w-auto grid mt-3" :style="`grid-template-columns:
repeat(${images.length < 6 ? images.length : 6}, minmax(0, 1fr))`">
<template x-for="image in images" :key="image.name">
<div
x-data="{
imgUrl: null
}"
x-init="() => {
let reader = new FileReader();
reader.onload = e => {
imgUrl = e.target.result;
};
console.log('image');
console.log(image);
reader.readAsDataURL(image);
}"
>
<img :src="imgUrl" alt="image.name" class="h-24 w-auto">
</div>
</template>
</div>
The problem I'm facing is that the grid container seems to be keeping the full width of its parent and the grid elements get these huge gaps between:
What I want is that each image to be nicely aligned on the left next to each other.
Snippet here
<script src="https://cdn.tailwindcss.com"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<style>
[x-cloak] { display: none !important }
</style>
<div
x-data="{
inputId: 'blabla',
selectedFileName: '',
fileInput: null,
multiple: true,
images: [],
imgCols: 0
}"
x-init="() => {
fileInput = document.getElementById(inputId);
}"
class="w-full"
x-on:drop="$event => {
$event.preventDefault();
const dataTransfer = new DataTransfer();
if (multiple) {
Array.from(fileInput.files).forEach(file => {
dataTransfer.items.add(file);
});
}
Array.from($event.dataTransfer.files).forEach(file => {
dataTransfer.items.add(file);
});
fileInput.files = dataTransfer.files;
if (!multiple) {
selectedFileName = $event.dataTransfer.files[0].name;
} else {
images = Array.from(fileInput.files);
}
fileInput.dispatchEvent(new Event('change', { bubbles: true }));
}"
x-on:dragover.prevent="() => console.log('drag over prevented')"
>
<label class="flex justify-center w-full h-32 px-4 transition bg-white border-2 border-gray-300 border-dashed rounded-md appearance-none cursor-pointer hover:border-gray-400 focus:outline-none"
>
<span class="flex items-center space-x-2">
<x-icon name="upload" />
<span class="font-medium text-gray-600">
drop or
<span class="text-blue-600 underline">browse</span>
</span>
</span>
<input id="blabla" type="file" name="file_upload" >
</label>
<div x-cloak class="w-full text-center" x-show="selectedFileName">
files selected: <span x-text="selectedFileName"></span>
</div>
<div x-show="multiple" class="w-auto grid mt-3" :style="`grid-template-columns: repeat(${images.length < 6 ? images.length : 6}, minmax(0, 1fr))`">
<template x-for="image in images" :key="image.name">
<div
x-data="{
imgUrl: null
}"
x-init="() => {
let reader = new FileReader();
reader.onload = e => {
imgUrl = e.target.result;
};
reader.readAsDataURL(image);
}"
>
<img :src="imgUrl" alt="image.name" class="h-24 w-auto">
</div>
</template>
</div>
</div>
Thanks.
The white space is caused by the grid track columns being wider than the images they contain. This is due to the minmax(0, 1fr)
value inside the repeat()
. This value means that the grid column tracks are allowed to increase in width to 1 "share" of space.
To prevent this behavior, you could consider using a different value inside the repeat()
, like max-content
:
<script src="https://cdn.tailwindcss.com"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<style>
[x-cloak] {
display: none !important;
}
</style>
<div
x-data="{
inputId: 'blabla',
selectedFileName: '',
fileInput: null,
multiple: true,
images: [],
imgCols: 0
}"
x-init="() => {
fileInput = document.getElementById(inputId);
}"
class="w-full"
x-on:drop="$event => {
$event.preventDefault();
const dataTransfer = new DataTransfer();
if (multiple) {
Array.from(fileInput.files).forEach(file => {
dataTransfer.items.add(file);
});
}
Array.from($event.dataTransfer.files).forEach(file => {
dataTransfer.items.add(file);
});
fileInput.files = dataTransfer.files;
if (!multiple) {
selectedFileName = $event.dataTransfer.files[0].name;
} else {
images = Array.from(fileInput.files);
}
fileInput.dispatchEvent(new Event('change', { bubbles: true }));
}"
x-on:dragover.prevent="() => console.log('drag over prevented')"
>
<label
class="flex justify-center w-full h-32 px-4 transition bg-white border-2 border-gray-300 border-dashed rounded-md appearance-none cursor-pointer hover:border-gray-400 focus:outline-none"
>
<span class="flex items-center space-x-2">
<x-icon name="upload" />
<span class="font-medium text-gray-600">
drop or
<span class="text-blue-600 underline">browse</span>
</span>
</span>
<input id="blabla" type="file" name="file_upload" />
</label>
<div x-cloak class="w-full text-center" x-show="selectedFileName">
files selected: <span x-text="selectedFileName"></span>
</div>
<div
x-show="multiple"
class="w-auto grid mt-3"
:style="`grid-template-columns: repeat(${images.length < 6 ? images.length : 6}, max-content)`"
>
<template x-for="image in images" :key="image.name">
<div
x-data="{
imgUrl: null
}"
x-init="() => {
let reader = new FileReader();
reader.onload = e => {
imgUrl = e.target.result;
};
reader.readAsDataURL(image);
}"
>
<img :src="imgUrl" alt="image.name" class="h-24 w-auto" />
</div>
</template>
</div>
</div>