File Upload
FrontAlign provides two file upload patterns: the native <input type="file"> with consistent styling, and a custom .group-file pattern that hides the native input behind a styled button and shows the selected filename next to it.
The custom pattern plugs into the same Form validation engine as every other field: it validates file extensions, enforces size limits, and surfaces the result through auto-generated feedback.
Native File Input
Apply .form-file to a standard file input. The built-in file selector button is styled to match the rest of the form system.
<div class="group">
<label class="form-label" for="avatar">Avatar</label>
<input class="form-file" id="avatar" type="file" />
</div>
Custom Upload Button
.group-file hides the native input visually and replaces it with a styled label as the click target. A .upload-display element next to the button shows the selected filename after the user picks a file. The .group-file local tag visually hides it and replaces it with a label configured as the click target. The .upload-display element, located next to the button, displays the name of the selected file after the user has chosen a file. For this to work correctly, a JS runtime is required. When you create a new frontAlign instance, the JS will run automatically.
<div class="group-file">
<input class="form-file" id="portfolio" type="file" />
<label class="form-label" for="portfolio">
<i class="icon-upload"></i> Upload file
</label>
<span class="upload-display">No file selected</span>
</div>
When a file is selected, the runtime writes the filename into .upload-display automatically — Selected: filename.ext for a single file, or N items selected when multiple files are chosen.
Runtime Validation
File inputs use the same data-rule engine documented on the Validation page — there's no separate set of file-specific attributes to learn. Two rules are built in: file-ext and file-max. Both live in the input's data-rule string alongside any other rule, evaluate through the same touched-state (blur/live) behavior as every other field, and are no-ops on any field that isn't type="file". If no file is selected, both pass automatically — pair them with required if a file must be present. See the Validation page for the full rule reference.
Extension Filter
Add file-ext to data-rule with a comma-separated, case-insensitive list of permitted extensions. If the user selects a file with a different extension, the rule fails and the engine's auto-generated feedback element shows the error message — no manual error markup required.
<div class="group-file">
<input
class="form-file"
id="photo"
type="file"
name="photo"
data-rule="file-ext:jpg,jpeg,png,webp"
data-error-msg="Only JPG, PNG, and WebP files are accepted."
/>
<label class="form-label" for="photo">Upload photo</label>
<span class="upload-display">No file selected</span>
</div>
Size Limit
Add file-max to data-rule, in megabytes. Multi-file inputs are covered too — the rule checks every selected file individually and fails if any one of them exceeds the limit.
<!-- 2 MB limit -->
<div class="group-file">
<input
class="form-file"
id="thumbnail"
type="file"
name="thumbnail"
data-rule="file-max:2"
data-error-msg="File must be smaller than 2 MB."
/>
<label class="form-label" for="thumbnail">Upload thumbnail</label>
<span class="upload-display">No file selected</span>
</div>
Auto-Generated Selection Text
The .upload-display element inside .group-file is kept in sync automatically on every change event — no manual JS needed:
| Selection | Display Text |
|---|---|
| No files | The value of data-default-text, or "No file selected". |
| One file | Selected: filename.ext |
| Multiple files | N items selected |
Size Variants
The custom upload button label accepts is-small, is-medium, and is-large to match surrounding form controls.
<div class="group-file">
<input class="form-file" id="upload-sm" type="file" />
<label class="form-label" for="upload-sm">Default</label>
<span class="upload-display">No file selected</span>
</div>
<div class="group-file">
<input class="form-file" id="upload-md" type="file" />
<label class="form-label is-medium" for="upload-md">Medium</label>
<span class="upload-display">No file selected</span>
</div>
<div class="group-file">
<input class="form-file" id="upload-lg" type="file" />
<label class="form-label is-large" for="upload-lg">Large</label>
<span class="upload-display">No file selected</span>
</div>
Disabled State
A disabled file input becomes non-interactive and drops to 50% opacity.
<div class="group">
<label class="form-label" for="locked-file">Attachment (locked)</label>
<input class="form-file" id="locked-file" type="file" disabled />
</div>