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>
No file selected

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:

SelectionDisplay Text
No filesThe value of data-default-text, or "No file selected".
One fileSelected: filename.ext
Multiple filesN 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>
No file selected
No file selected
No file selected

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>

FrontAlign