A single-image upload control with a live preview. Wrap a native
<input type="file">
in
.wf-imgup[data-wf-image-upload]
and the JS replaces it with a clickable preview area. The native input stays hidden, so standard form submissions work with zero changes.
Basic
Drag-and-drop is supported in all shapes. Validation errors (type, file size, and pixel dimensions) are surfaced via
WojoToast
. An initial server image can be shown via
data-wf-preview-src
.
Set
data-wf-shape
to one of four values. The default is
rounded
. All shapes are square aspect ratio except
rectangle
, which uses a wide 16:9 proportion.
Client-side validation runs on every file selection and drag-drop. Failures are shown as toast notifications via
WojoToast
and the input is reset so the same file can be corrected and re-submitted. Three types of checks are available and can be combined freely.
Min and max width/height are checked after the file passes the size test. Mix and match as needed — any omitted limit defaults to unlimited (0).
HTML
<!-- Banner: at least 400px wide, max 1920×640 -->
<div class="wf-imgup" data-wf-image-upload
data-wf-shape="rectangle"
data-wf-min-width="400"
data-wf-max-width="1920"
data-wf-max-height="640">
<input type="file" name="banner" accept="image/jpeg,image/png,image/webp">
</div>
Pre-populate
Use
data-wf-preview-src
to show the currently saved image on page load — for example when rendering an edit form server-side. No file is staged; the attribute is display-only. The user can then pick a new file to replace it or click the remove button to clear it.
Place all attributes on the
.wf-imgup
wrapper element.
Attribute
Values / Default
Description
data-wf-image-upload
—
Required.
Marks the wrapper for auto-init on DOMContentLoaded.
data-wf-shape
rounded · square · circle ·
rectangle Default: rounded
Preview shape. rectangle uses a wide aspect ratio; all others are square.
data-wf-size
sm · lg
Size preset. Omit for medium (default). Adjusts the preview area and icon size.
data-wf-max-size
integer (bytes) Default: 0 (unlimited)
Maximum file size in bytes. Files exceeding this limit are rejected with a toast error.
data-wf-max-width
integer (px) Default: 0 (unlimited)
Maximum image width in pixels.
data-wf-max-height
integer (px) Default: 0 (unlimited)
Maximum image height in pixels.
data-wf-min-width
integer (px) Default: 0 (unlimited)
Minimum image width in pixels.
data-wf-min-height
integer (px) Default: 0 (unlimited)
Minimum image height in pixels.
data-wf-preview-src
URL string
Initial image URL shown on page load (e.g., currently saved server image). Display-only —
no File is staged.
data-wf-preview-class
CSS class string
One or more extra CSS classes added to the .wf-imgup-preview element.
data-wf-disabled
—
Disables the control and mirrors disabled on the native input.
Show More
Native input attributes
Placed on the
<input type="file">
inside the wrapper. The
multiple
attribute is always removed — this component is single-file only.
Attribute
Description
accept
Restrict the file picker and validate dropped files. Defaults to image/* if omitted. Accepts MIME types (image/jpeg), wildcards (image/*), or extensions (.jpg).
disabled
Also disables the component UI.
name
Used for normal form submission.
CSS Custom Properties
These properties are declared on
:root
and can be overridden on
.wf-imgup
or any ancestor.
Width and height of square shapes (rounded, square, circle). Overridden by sm/lg presets.
--wf-imgup-rect-w
18rem
Width of the rectangle shape.
--wf-imgup-rect-h
10rem
Height of the rectangle shape.
--wf-imgup-border
var(--wf-border)
Dashed border color of the preview area.
--wf-imgup-bg
var(--wf-surface-subtle)
Background of the preview area when empty.
--wf-imgup-overlay-bg
rgba(0,0,0,.45)
The background of the hover overlay is shown when an image is loaded.
--wf-imgup-speed
.2s
Transition duration for hover, drag, and image fade effects.
--wf-imgup-ease
ease
Transition easing function.
Programmatic API
After initialization the instance is stored on the wrapper element as
el._wfImageUpload
.
JS
const el = document.querySelector('[data-wf-image-upload]')
const uploader = el._wfImageUpload
uploader.setPreviewUrl('/uploads/saved.jpg') // show server image
uploader.getFile() // returns File or null
uploader.clear() // remove preview & reset
uploader.setDisabled(true) // disable
uploader.destroy() // remove listeners & revoke URL
Method
Returns
Description
setPreviewUrl(url)
—
Show a remote or server image URL as the preview. Clears any currently staged local File. Does not fire events.
getFile()
File | null
Returns the currently staged File, or null if only a remote URL is shown or the control is empty.
clear()
—
Remove the preview image, reset the native input, and fire wf:image-remove.
setDisabled(bool)
—
Enable or disable the component and the underlying native input.
destroy()
—
Remove all event listeners and revoke any pending object URL.
Events
Both events are dispatched on the
.wf-imgup
wrapper and bubble up the DOM.
JS
const el = document.querySelector('[data-wf-image-upload]')
el.addEventListener('wf:image-change', e => {
console.log('New image file:', e.detail.file)
// e.detail.file is the validated File object
})
el.addEventListener('wf:image-remove', () => {
console.log('Image was cleared')
})
Event
detail
Fired when
wf:image-change
{ file }
A new image passes all validation and its preview is shown. file is the File object.
wf:image-remove
—
The preview image is cleared by the remove button or by calling clear().
i18n
Register a locale globally with
WojoI18n
before
DOMContentLoaded
. Any key you omit falls back to the built-in English default. Use
{max}
in error size messages and
{min}
/
{max}
in dimension messages.
JS
import { WojoI18n } from './wf-base.js'
WojoI18n.setLocale('fr')
WojoI18n.register('fr', {
imageUpload: {
chooseLabel: 'Choisir une image',
changeLabel: 'Changer l\'image',
removeLabel: 'Supprimer',
placeholderLabel: 'Cliquez ou déposez une image',
errorType: 'Type de fichier invalide.',
errorSize: 'Fichier trop volumineux. Max : {max}.',
errorMinWidth: 'Image trop étroite. Largeur min : {min}px.',
errorMinHeight: 'Image trop petite. Hauteur min : {min}px.',
errorMaxWidth: 'Image trop large. Largeur max : {max}px.',
errorMaxHeight: 'Image trop haute. Hauteur max : {max}px.',
}
})
HTML
<!-- Per-instance overrides (highest priority) -->
<div class="wf-imgup" data-wf-image-upload
data-wf-i18n-choose-label="Wählen Sie ein Bild"
data-wf-i18n-placeholder-label="Klicken oder ablegen"
data-wf-i18n-error-size="Datei zu groß. Max: {max}.">
<input type="file" name="avatar" accept="image/*">
</div>
i18n keys
Key
data-wf-i18n-* attribute
Default (English)
chooseLabel
data-wf-i18n-choose-label
Choose an image (aria-label when empty)
changeLabel
data-wf-i18n-change-label
Change image (aria-label when filled)
removeLabel
data-wf-i18n-remove-label
Remove (aria-label for × button)
placeholderLabel
data-wf-i18n-placeholder-label
Click or drop the image
errorType
data-wf-i18n-error-type
Invalid file type.
errorSize
data-wf-i18n-error-size
File is too large. Max: {max}.
errorMinWidth
data-wf-i18n-error-min-width
Image is too narrow. Min width: {min}px.
errorMinHeight
data-wf-i18n-error-min-height
Image is too short. Min height: {min}px.
errorMaxWidth
data-wf-i18n-error-max-width
Image is too wide. Max width: {max}px.
errorMaxHeight
data-wf-i18n-error-max-height
Image is too tall. Max height: {max}px.
Class Reference
All modifier classes available on
.wf-imgup
Class
Description
wf-imgup
Root wrapper. Add data-wf-image-upload for auto-init. JS sets data-wf-has-image when a preview is loaded and data-wf-dragging during active drag.
wf-imgup--rounded
Shape modifier — large rounded corners (default). Applied by JS based on data-wf-shape.
wf-imgup--square
Shape modifier — minimal border radius.
wf-imgup--circle
Shape modifier — 50% radius. Placeholder text is hidden in this variant.
wf-imgup--rectangle
Shape modifier — wide aspect ratio, sized by --wf-imgup-rect-w and --wf-imgup-rect-h.
wf-imgup-preview
The clickable preview area (also the drag-and-drop target). Has role="button" and keyboard support. Opening the file picker and showing the overlay are handled here.
wf-imgup-img
The <img> element inside the preview. Hidden (opacity:0) when empty; fades in when data-wf-has-image is set.
wf-imgup-placeholder
Icon and text are shown when no image is loaded. Fades out when an image is set.
wf-imgup-placeholder-icon
Image icon inside the placeholder.
wf-imgup-placeholder-text
“Click or drop image” text inside the placeholder. Hidden for the circle shape.
wf-imgup-overlay
Semi-transparent overlay with a camera icon. Visible on hover/focus when an image is loaded, indicating the preview is clickable to change.
wf-imgup-remove
Small circular × button positioned in the top-right corner of the preview. Hidden (display:none) when no image is loaded; shown when data-wf-has-image is set.