HTML date input default value

The value attribute takes one format, YYYY-MM-DD, regardless of how the field is displayed in the reader's locale. Defaulting to today needs one line of script, written carefully enough to survive timezones.

The default value of an HTML date input is set with the value attribute, and it must be an ISO date: YYYY-MM-DD.

<input type="date" name="due" value="2026-09-16">

That is the only format accepted, no matter how the field appears on screen.

A date input prefilled with a value, displayed in the reader's own locale format.
A date input prefilled with a value, displayed in the reader's own locale format.

A reader in one country sees 16/09/2026 and a reader in another sees 9/16/2026. Both are the same attribute. The display is the browser's business, not yours.

Why a valid-looking value gets ignored

The field renders empty rather than complaining, so a format mistake looks like the attribute did nothing.

Value you wrote Result
2026-09-16 Works
2026-9-16 Ignored, needs zero padding
16/09/2026 Ignored
Sept 16, 2026 Ignored
2026-09-16T00:00 Ignored by type="date", correct for datetime-local
today Ignored, there is no such keyword

The last row is the one people try first. HTML has no notion of the current date, so there is nothing to put in the attribute.

Defaulting to today

One line, and the obvious version of it has a bug.

// Wrong near midnight and in some timezones
input.value = new Date().toISOString().slice(0, 10);

toISOString converts to UTC. If you are ahead of UTC in the early morning or behind it in the evening, that string is yesterday or tomorrow.

Build it from local parts instead:

const d = new Date();
const pad = (n) => String(n).padStart(2, '0');
input.value = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;

getMonth is zero-based, which is the second bug in this area. January is 0, so the month always needs the plus one.

A shorter version that is also correct:

input.value = new Date().toLocaleDateString('en-CA');

The Canadian English locale formats dates as YYYY-MM-DD and uses local time. It reads as a trick, so leave a comment next to it.

The date field on load, already carrying the current date without the reader touching it.
The date field on load, already carrying the current date without the reader touching it.

Limiting the range

Defaults are usually paired with bounds. min and max take the same ISO format and the picker greys out everything outside them.

<input type="date" name="start" min="2026-09-16" max="2026-12-31" value="2026-09-16">

Useful combinations:

  • No past dates. Set min to today, for booking and delivery fields.
  • No future dates. Set max to today, for a date of birth or an incident report.
  • Inside a period. Both bounds, for anything tied to a quarter or a term.

A default outside the range is discarded, so set the bounds and the value from the same calculation.

Bounds are a convenience, not a guarantee. The value still arrives from the browser, so check it again wherever you receive it, in the same way you would check a hidden field.

Reading and writing the value from script. Three properties do slightly different things.

  • input.value is the ISO string, or an empty string if the field is blank or invalid.
  • input.valueAsDate is a Date object in UTC, or null. Convenient for arithmetic, a source of off-by-one errors for display.
  • input.defaultValue is what the attribute said. It is where the field returns to when the form is reset.

Setting a date a week ahead:

const d = new Date();
d.setDate(d.getDate() + 7);
input.value = d.toLocaleDateString('en-CA');

setDate rolls over month and year ends on its own, so no special handling is needed for the end of December.

Whether to prefill at all

A default is a suggestion, and people accept suggestions. That is useful when the suggestion is usually right and harmful when it is not.

Prefill today's date on a log entry, a timesheet row or an incident report, where today is the answer most of the time and a wrong value is obvious.

Leave the field empty on a date of birth, an appointment, or anything where the reader has to think. A prefilled value there is quietly accepted by a proportion of people who never meant to submit it, and you cannot tell those rows apart afterwards.

A middle option exists: prefill, and show the value as a suggestion the reader has to confirm. A small note next to the field saying which date is currently selected costs nothing and catches the accidental submissions.

Whatever you choose, record on the receiving end whether the value was the default or was changed. That single flag makes the data answer questions the date alone cannot.

Type Value format Common use
date 2026-09-16 A single day
time 14:30 A clock time, no date
datetime-local 2026-09-16T14:30 Appointment, no timezone attached
month 2026-09 Billing periods, reporting months
week 2026-W38 Sprint and rota planning

datetime-local carries no timezone by design. If the moment matters across regions, store the offset separately rather than assuming the reader's.

Checking it in a clean window

Prefilled dates fail quietly, so look at the rendered field rather than the source.

The form open in the HTML file opener, with the date field showing the prefilled value.
The form open in the HTML file opener, with the date field showing the prefilled value.

Paste the page into the HTML file opener and look at the box. If it is empty, the format is wrong or the value falls outside your min and max.

Reload once after midnight, or change the machine clock, if the field defaults to today. That is where the UTC bug shows up.

Sending the form out

A finished form page still has to reach people, and an .html file with a form and script inside is routinely stripped by mail gateways before it arrives.

Paste the HTML into a NOS document. It renders as written at its own address. Share, then Share link, then Create link, and send the link.

The address stays the same through edits, so adjusting a bound or a label later does not mean resending. Turning a form into a link covers the route, and posting the answers into a spreadsheet covers where the dates end up.

Questions people ask

How do I set a default value on an HTML date input?

Put an ISO date in the value attribute: value="2026-09-16". It must be YYYY-MM-DD with the zero padding, even if the browser displays the field as DD/MM/YYYY. Any other format is ignored and the field renders empty.

How do I default a date input to today?

There is no HTML-only way. Set it with a line of script on load. Build the string from the local year, month and day rather than from toISOString, which converts to UTC and can land you a day out.

Why is my date input showing empty when I set a value?

Almost always a format problem. 16/09/2026, Sept 16 2026 and 2026-9-16 are all rejected. The month and day need two digits. A value outside a min or max range you set will also be refused.

Can I change the display format of a date input?

No. The browser renders it using the reader's locale settings and there is no attribute to override that. If you need a fixed display format you have to build the field from text inputs yourself, which loses the native picker.

Keep reading