Skip to content

Edit Profile Form with Photo Upload

Tailwind CSS edit profile form with drag-and-drop photo upload and live preview, bio character counter, social link fields and simulated save.

Also known as: profile settings page, account settings form, avatar upload form, user profile form

Edit Profile Form with Photo Upload live demo

Open in new tab

Tailwind CSS code (HTML, CSS, JS)

An edit profile form built with Tailwind CSS and vanilla JavaScript: a photo column with drag-and-drop upload and instant preview, plus personal details, a bio with a character counter and four social link fields. Use it as the settings or account page of a SaaS app, community site or portfolio platform.

How it works

The root is section.epu-profile, which wraps a single form with data-epu-form. On large screens a two-column grid (lg:grid-cols-[18rem_1fr]) places the photo aside next to the details card; on phones both stack.

The avatar is .epu-avatar with an <img data-epu-preview> and an initials fallback (data-epu-initials). The real file input (#epu-file, data-epu-file) is visually hidden; the camera badge and the "Choose a file" link are label elements pointing to it, and the dashed .epu-drop zone also accepts dropped files. On change or drop the script checks the MIME type and the size limit, creates a preview with URL.createObjectURL() and revokes the previous URL to free memory. "Remove photo" adds .is-empty to the avatar, which hides the image and shows the initials.

The bio textarea updates the data-epu-count counter on every input event. The "Public preview" card in the photo column mirrors the name and username as you type. On submit the script runs checkValidity() on every field, marks failures with aria-invalid="true" and focuses the first one; otherwise it shows a spinner and "Saving…" for 900 ms and then reports "Profile saved.". "Discard changes" is a native reset button, and the reset handler restores the original photo, counter and preview.

Customization

  • data-epu-max-mb="2" on #epu-file: raise or lower the maximum upload size; the error message uses the same value.
  • accept on #epu-file and the ACCEPTED array in script.js: allow other formats such as GIF or AVIF.
  • maxlength="200" on #epu-bio: change the bio limit; the counter reads it automatically and turns amber within 20 characters.
  • teal-700, teal-50 and focus:ring-teal-600/15: swap teal for indigo or orange to rebrand buttons, rings and the preview card.
  • rounded-3xl on both cards and rounded-xl on inputs: use smaller radii for a sharper look.
  • The setTimeout in the submit handler: replace it with fetch() and a FormData(form) body to save to your API.
  • pattern="[a-z0-9_]{3,20}" on #epu-username: adjust the allowed username format.

Use cases

  • SaaS apps: the account or settings page where users change their photo and details
  • Community and social sites: a profile editor with bio and social links
  • Portfolio platforms: let creators update their public profile

Accessibility

Every field has a visible label; the two groups use fieldset and legend. The hidden file input remains in the tab order, and .epu-drop:focus-within draws a visible outline around the drop zone when it receives keyboard focus. Upload errors and the save result are announced through aria-live regions, and the counter only announces the remaining characters near the limit. Decorative icons are aria-hidden. Animations (photo pop, spinner) stop under prefers-reduced-motion: reduce.

Usage notes

The sample portrait comes from Unsplash; replace it with the user's own photo URL. Uploads are never sent anywhere: wire the fetch() call yourself. For several forms on one page give each copy unique id values.

Edit Profile Form with Photo Upload at a glance

Framework
Tailwind CSS
Code
HTML, CSS, JavaScript
JavaScript
Vanilla JavaScript, no jQuery
Dependencies
Tailwind CSS
Layout
Responsive, works on mobile
Category
Profile Pages
License
Free for personal and commercial use

Questions about this template

Can I use the Edit Profile Form with Photo Upload code for free?

Yes. You can copy or download the code and use it in personal and commercial projects, including client work. No sign-up is needed. Reselling it as part of a component library or template collection is not allowed; see the license.

How do I add it to my website?

Load Tailwind CSS from a CDN (the links are under Requirements). Paste the HTML where the component should appear, add the CSS to your stylesheet and load the JavaScript before the closing </body> tag. Download HTML gives you a complete page with everything already linked.

Does it need jQuery or a JavaScript framework?

No. The script is plain vanilla JavaScript, so it works without jQuery, React or Vue. You can still use the markup inside those frameworks.

Does it work on mobile?

Yes. The layout adapts to small screens. Use the Mobile and Tablet buttons above the live demo to check it at phone and tablet width.

Requirements

Add these to your page (already included in the download):

  • <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

The Tailwind browser build is for prototyping. In production, compile Tailwind with its CLI or your bundler.

Edit Profile Form with Photo Upload – Tailwind CSS profile pages component screenshot
Edit Profile Form with Photo Upload · Tailwind CSS Profile Pages

More Profile Pages

Account Settings Page with Tabs – Bootstrap 5 profile pages preview

Account Settings Page with Tabs

Bootstrap 5 account settings page with profile, security and notification tabs, password strength meter, session list and simulated save.