# Emergency contact form template

A free online emergency contact form with two contacts, their relationship and phone numbers, and optional medical notes. Copy the HTML, CSS and JS, or use it in React, Next.js, Vue, Svelte or Astro.

This form asks for the person’s name and email, one required contact with their relationship and phone number, an optional second contact, and an optional field for allergies or medication. You can search submissions by name in your inbox.

Live preview, field editor, four themes and styled versions for every framework: https://nisuform.com/templates/emergency-contact-form

## Fields

| Field | Name | Type | Required |
| --- | --- | --- | --- |
| Full name | `name` | Short text | Yes |
| Email | `email` | Email | Yes |
| Emergency contact name | `contact_name` | Short text | Yes |
| Relationship to you | `contact_relationship` | Dropdown (Spouse or partner, Parent, Child, Sibling, Friend, Other) | Yes |
| Emergency contact phone | `contact_phone` | Phone | Yes |
| Second contact name | `second_contact_name` | Short text | No |
| Second contact phone | `second_contact_phone` | Phone | No |
| Medical notes | `medical_notes` | Long text | No |

## How to use it

1. Create a free form at https://app.nisuform.com and copy its form key.
2. Paste the code where the form should appear and replace `YOUR_FORM_KEY` with your key.
3. Submit the form once. The submission appears in your Nisuform inbox and you get an email.

## Styled HTML, CSS and JavaScript

The form with its styles and a small script that sends it without a page reload and shows the success message.

```html
<form id="nf-emergency-contact-form" class="nf-form" action="https://api.nisuform.com/s/YOUR_FORM_KEY" method="POST">
  <style>
#nf-emergency-contact-form {
  --nf-accent: #e60058;
  --nf-on-accent: #ffffff;
  --nf-text: #171717;
  --nf-muted: #525252;
  --nf-field: #f5f5f5;
  --nf-field-text: #171717;
  --nf-placeholder: #6b6b6b;
  --nf-control: #8a8a8a;
  --nf-error: #b91c1c;
  color-scheme: light;
  box-sizing: border-box;
  width: 100%;
  max-width: 480px;
  margin: 0;
  padding: 28px;
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 16px;
  background: linear-gradient(180deg, #ffffff, #ffffff);
  box-shadow: 0 16px 40px -16px rgba(0, 0, 0, 0.12);
  color: var(--nf-text);
  font: inherit;
  font-size: 16px;
  line-height: 1.5;
  text-align: left;
}
#nf-emergency-contact-form *, #nf-emergency-contact-form *::before, #nf-emergency-contact-form *::after { box-sizing: border-box; }
#nf-emergency-contact-form [hidden] { display: none !important; }
#nf-emergency-contact-form .nf-title { margin: 0; font-size: 1.25em; font-weight: 650; line-height: 1.25; letter-spacing: -0.01em; color: var(--nf-text); }
#nf-emergency-contact-form .nf-desc { margin: 6px 0 0; font-size: 0.9375em; color: var(--nf-muted); }
#nf-emergency-contact-form .nf-fields { display: grid; gap: 18px; margin-top: 22px; }
#nf-emergency-contact-form .nf-head + .nf-fields { margin-top: 22px; }
#nf-emergency-contact-form > .nf-fields:first-child { margin-top: 0; }
#nf-emergency-contact-form .nf-field { margin: 0; padding: 0; border: 0; min-width: 0; }
#nf-emergency-contact-form .nf-label { display: block; margin: 0 0 6px; padding: 0; font-size: 0.875em; font-weight: 600; color: var(--nf-text); }
#nf-emergency-contact-form .nf-req { color: var(--nf-muted); font-weight: 400; }
#nf-emergency-contact-form .nf-help { margin: 6px 0 0; font-size: 0.8125em; color: var(--nf-muted); }
#nf-emergency-contact-form .nf-input { display: block; width: 100%; margin: 0; padding: 10px 12px; border: 1px solid transparent; border-radius: 10px; background: var(--nf-field); color: var(--nf-field-text); font: inherit; font-size: 1em; line-height: 1.4; outline: 2px solid transparent; outline-offset: 1px; transition: border-color 150ms, box-shadow 150ms; }
#nf-emergency-contact-form input.nf-input, #nf-emergency-contact-form select.nf-input { height: 2.75em; padding-top: 0; padding-bottom: 0; }
#nf-emergency-contact-form textarea.nf-input { min-height: 112px; padding-top: 10px; padding-bottom: 10px; resize: vertical; }
#nf-emergency-contact-form .nf-input::placeholder { color: var(--nf-placeholder); opacity: 1; }
#nf-emergency-contact-form .nf-input:hover { border-color: color-mix(in srgb, var(--nf-text) 14%, transparent); }
#nf-emergency-contact-form .nf-input:focus { border-color: var(--nf-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--nf-accent) 24%, transparent); }
#nf-emergency-contact-form .nf-input:user-invalid { border-color: var(--nf-error); }
#nf-emergency-contact-form .nf-input:user-invalid:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--nf-error) 24%, transparent); }
#nf-emergency-contact-form .nf-input:-webkit-autofill { -webkit-text-fill-color: var(--nf-field-text); caret-color: var(--nf-field-text); box-shadow: inset 0 0 0 100px var(--nf-field); }
#nf-emergency-contact-form .nf-input:-webkit-autofill:focus { box-shadow: inset 0 0 0 100px var(--nf-field), 0 0 0 3px color-mix(in srgb, var(--nf-accent) 24%, transparent); }
#nf-emergency-contact-form input[type="number"].nf-input { -moz-appearance: textfield; appearance: textfield; }
#nf-emergency-contact-form input[type="number"].nf-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
#nf-emergency-contact-form input[type="number"].nf-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
#nf-emergency-contact-form input[type="date"].nf-input { min-width: 0; text-align: left; }
#nf-emergency-contact-form input[type="date"].nf-input::-webkit-date-and-time-value { text-align: left; }
#nf-emergency-contact-form input[type="date"].nf-input.nf-empty:not(:focus) { color: var(--nf-placeholder); }
#nf-emergency-contact-form input[type="date"].nf-input::-webkit-calendar-picker-indicator { margin: 0; padding: 4px; border-radius: 6px; opacity: 0.55; cursor: pointer; transition: opacity 150ms; }
#nf-emergency-contact-form input[type="date"].nf-input::-webkit-calendar-picker-indicator:hover { opacity: 1; }
#nf-emergency-contact-form select.nf-input { -webkit-appearance: none; appearance: none; padding-right: 40px; background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23525252%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M6%209l6%206l6%20-6%22%2F%3E%3C%2Fsvg%3E"); background-repeat: no-repeat; background-position: right 12px center; background-size: 16px 16px; cursor: pointer; }
#nf-emergency-contact-form select.nf-input:has(option[value=""]:checked) { color: var(--nf-placeholder); }
#nf-emergency-contact-form select.nf-input option { color: var(--nf-field-text); }
#nf-emergency-contact-form .nf-options { display: grid; gap: 8px; }
#nf-emergency-contact-form .nf-option { display: flex; align-items: center; gap: 10px; min-height: 2.75em; margin: 0; padding: 10px 12px; border: 1px solid color-mix(in srgb, var(--nf-text) 14%, transparent); border-radius: 10px; background: transparent; color: var(--nf-text); font-size: 0.9375em; line-height: 1.4; cursor: pointer; transition: border-color 150ms, background-color 150ms; }
#nf-emergency-contact-form .nf-option:hover { border-color: color-mix(in srgb, var(--nf-text) 28%, transparent); }
#nf-emergency-contact-form .nf-option:has(input:checked) { border-color: var(--nf-accent); background: color-mix(in srgb, var(--nf-accent) 8%, transparent); }
#nf-emergency-contact-form .nf-option span { min-width: 0; overflow-wrap: anywhere; }
#nf-emergency-contact-form .nf-option input { -webkit-appearance: none; appearance: none; flex: none; width: 18px; height: 18px; margin: 0; border: 1.5px solid var(--nf-control); border-radius: 50%; background: transparent; outline: 2px solid transparent; cursor: pointer; transition: border-color 150ms, box-shadow 150ms; }
#nf-emergency-contact-form .nf-option input:checked { border-color: var(--nf-accent); background: radial-gradient(circle, var(--nf-on-accent) 0 3px, var(--nf-accent) 3.5px); }
#nf-emergency-contact-form .nf-option input:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--nf-accent) 24%, transparent); }
#nf-emergency-contact-form .nf-check { display: flex; align-items: flex-start; gap: 10px; margin: 0; font-size: 0.9375em; line-height: 1.5; color: var(--nf-text); cursor: pointer; }
#nf-emergency-contact-form .nf-check input { -webkit-appearance: none; appearance: none; flex: none; width: 20px; height: 20px; margin: 1px 0 0; border: 1.5px solid var(--nf-control); border-radius: 6px; background: var(--nf-field) center / 14px 14px no-repeat; outline: 2px solid transparent; cursor: pointer; transition: background-color 150ms, border-color 150ms, box-shadow 150ms; }
#nf-emergency-contact-form .nf-check input:checked { border-color: var(--nf-accent); background-color: var(--nf-accent); background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23ffffff%22%20stroke-width%3D%223.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M5%2012l5%205l10%20-10%22%2F%3E%3C%2Fsvg%3E"); }
#nf-emergency-contact-form .nf-check input:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--nf-accent) 24%, transparent); }
#nf-emergency-contact-form .nf-check input:user-invalid { border-color: var(--nf-error); }
#nf-emergency-contact-form .nf-rating { display: flex; flex-wrap: wrap; margin: 0 0 0 -4px; }
#nf-emergency-contact-form .nf-rating label { display: inline-flex; padding: 4px; border-radius: 8px; color: var(--nf-control); color: color-mix(in srgb, var(--nf-control) 45%, transparent); cursor: pointer; transition: color 150ms; }
#nf-emergency-contact-form .nf-rating svg { width: 30px; height: 30px; fill: currentColor; stroke: currentColor; stroke-width: 1.5; stroke-linejoin: round; transition: transform 150ms; }
#nf-emergency-contact-form .nf-rating input:checked + label, #nf-emergency-contact-form .nf-rating label:has(~ input:checked) { color: var(--nf-accent); }
#nf-emergency-contact-form .nf-rating:hover input + label { color: var(--nf-control); color: color-mix(in srgb, var(--nf-control) 45%, transparent); }
#nf-emergency-contact-form .nf-rating:hover label:hover, #nf-emergency-contact-form .nf-rating:hover label:has(~ label:hover) { color: var(--nf-accent); }
#nf-emergency-contact-form .nf-rating label:active svg { transform: scale(0.88); }
#nf-emergency-contact-form .nf-rating input:focus-visible + label { outline: 2px solid var(--nf-accent); outline-offset: 0; }
#nf-emergency-contact-form .nf-file { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; min-height: 112px; padding: 16px; border: 1.5px dashed var(--nf-control); border-color: color-mix(in srgb, var(--nf-control) 55%, transparent); border-radius: 10px; background: var(--nf-field); color: var(--nf-muted); text-align: center; transition: border-color 150ms, background-color 150ms, box-shadow 150ms; }
#nf-emergency-contact-form .nf-file-input { position: absolute; top: 0; left: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
#nf-emergency-contact-form .nf-file svg { width: 22px; height: 22px; margin-bottom: 4px; }
#nf-emergency-contact-form .nf-file-text { margin: 0; max-width: 100%; font-size: 0.875em; overflow-wrap: anywhere; }
#nf-emergency-contact-form .nf-file-cta { font-weight: 600; color: var(--nf-text); }
#nf-emergency-contact-form .nf-file-types { margin: 0; font-size: 0.75em; color: var(--nf-placeholder); }
#nf-emergency-contact-form .nf-file:hover { border-color: var(--nf-control); }
#nf-emergency-contact-form .nf-file:focus-within { border-color: var(--nf-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--nf-accent) 24%, transparent); }
#nf-emergency-contact-form .nf-file.nf-file-over { border-color: var(--nf-accent); background: color-mix(in srgb, var(--nf-accent) 8%, var(--nf-field)); }
#nf-emergency-contact-form .nf-file.nf-file-chosen { border-style: solid; border-color: var(--nf-accent); }
#nf-emergency-contact-form .nf-file.nf-file-chosen .nf-file-text { font-weight: 600; color: var(--nf-text); }
#nf-emergency-contact-form .nf-file:has(.nf-file-input:user-invalid) { border-color: var(--nf-error); }
#nf-emergency-contact-form .nf-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
#nf-emergency-contact-form .nf-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
#nf-emergency-contact-form .nf-captcha { margin-top: 18px; }
#nf-emergency-contact-form .nf-submit { display: inline-flex; align-items: center; justify-content: center; width: 100%; min-height: 44px; margin: 22px 0 0; padding: 10px 18px; border: 0; border-radius: 10px; background: var(--nf-accent); color: var(--nf-on-accent); font: inherit; font-size: 1em; font-weight: 600; cursor: pointer; transition: filter 150ms, transform 150ms; }
#nf-emergency-contact-form .nf-submit:hover { filter: brightness(0.94); }
#nf-emergency-contact-form .nf-submit:active { transform: scale(0.98); }
#nf-emergency-contact-form .nf-submit:focus-visible { outline: 2px solid var(--nf-accent); outline-offset: 3px; }
#nf-emergency-contact-form .nf-submit:disabled { opacity: 0.6; cursor: default; }
#nf-emergency-contact-form .nf-error { margin: 14px 0 0; padding: 10px 12px; border-radius: 10px; background: color-mix(in srgb, var(--nf-error) 10%, transparent); font-size: 0.875em; color: var(--nf-error); }
#nf-emergency-contact-form.nf-sent { display: flex; flex-direction: column; justify-content: center; min-height: min(var(--nf-height, 0px), 440px); }
#nf-emergency-contact-form .nf-success { display: flex; flex-direction: column; align-items: center; padding: 20px 0; text-align: center; outline: none; }
#nf-emergency-contact-form .nf-success-icon { display: flex; flex: none; align-items: center; justify-content: center; width: 56px; height: 56px; margin: 0 0 20px; border-radius: 50%; background: var(--nf-accent); color: var(--nf-on-accent); box-shadow: 0 0 0 8px color-mix(in srgb, var(--nf-accent) 12%, transparent); }
#nf-emergency-contact-form .nf-success-icon svg { display: block; width: 28px; height: 28px; margin: 0; stroke-dasharray: 1; }
#nf-emergency-contact-form .nf-success-title { margin: 0; max-width: 24em; font-size: 1.125em; font-weight: 650; line-height: 1.35; letter-spacing: -0.01em; color: var(--nf-text); text-wrap: balance; overflow-wrap: anywhere; }
#nf-emergency-contact-form .nf-success-text { margin: 0; max-width: 30em; font-size: 0.9375em; line-height: 1.5; color: var(--nf-text); text-wrap: pretty; overflow-wrap: anywhere; }
#nf-emergency-contact-form .nf-success-title + .nf-success-text { margin-top: 6px; color: var(--nf-muted); }
#nf-emergency-contact-form.nf-sent .nf-success { animation: nf-success-in 400ms cubic-bezier(0.16, 1, 0.3, 1) both; }
#nf-emergency-contact-form.nf-sent .nf-success-icon { animation: nf-success-pop 500ms cubic-bezier(0.34, 1.56, 0.64, 1) both; }
#nf-emergency-contact-form.nf-sent .nf-success-icon path { animation: nf-success-draw 360ms 160ms cubic-bezier(0.65, 0, 0.35, 1) both; }
@keyframes nf-success-in { from { opacity: 0; transform: translateY(6px); } }
@keyframes nf-success-pop { from { transform: scale(0.6); } }
@keyframes nf-success-draw { from { stroke-dashoffset: 1; } }
@media (prefers-reduced-motion: reduce) { #nf-emergency-contact-form * { transition: none !important; animation: none !important; } }
  </style>
  <div class="nf-head">
    <h2 class="nf-title">Emergency contact</h2>
    <p class="nf-desc">Who should we call if something happens to you?</p>
  </div>
  <div class="nf-fields">
    <div class="nf-field">
      <label class="nf-label" for="nf-emergency-contact-form-name">Full name<span class="nf-req" aria-hidden="true"> *</span></label>
      <input class="nf-input" id="nf-emergency-contact-form-name" name="name" type="text" autocomplete="name" placeholder="Jane Smith" required>
    </div>
    <div class="nf-field">
      <label class="nf-label" for="nf-emergency-contact-form-email">Email<span class="nf-req" aria-hidden="true"> *</span></label>
      <input class="nf-input" id="nf-emergency-contact-form-email" name="email" type="email" autocomplete="email" placeholder="jane@example.com" required>
    </div>
    <div class="nf-field">
      <label class="nf-label" for="nf-emergency-contact-form-contact_name">Emergency contact name<span class="nf-req" aria-hidden="true"> *</span></label>
      <input class="nf-input" id="nf-emergency-contact-form-contact_name" name="contact_name" type="text" placeholder="Sam Smith" required>
    </div>
    <div class="nf-field">
      <label class="nf-label" for="nf-emergency-contact-form-contact_relationship">Relationship to you<span class="nf-req" aria-hidden="true"> *</span></label>
      <select class="nf-input" id="nf-emergency-contact-form-contact_relationship" name="contact_relationship" required>
        <option value="">Choose one</option>
        <option value="Spouse or partner">Spouse or partner</option>
        <option value="Parent">Parent</option>
        <option value="Child">Child</option>
        <option value="Sibling">Sibling</option>
        <option value="Friend">Friend</option>
        <option value="Other">Other</option>
      </select>
    </div>
    <div class="nf-field">
      <label class="nf-label" for="nf-emergency-contact-form-contact_phone">Emergency contact phone<span class="nf-req" aria-hidden="true"> *</span></label>
      <input class="nf-input" id="nf-emergency-contact-form-contact_phone" name="contact_phone" type="tel" autocomplete="tel" placeholder="+1 555 0100" required>
    </div>
    <div class="nf-field">
      <label class="nf-label" for="nf-emergency-contact-form-second_contact_name">Second contact name</label>
      <input class="nf-input" id="nf-emergency-contact-form-second_contact_name" name="second_contact_name" type="text">
    </div>
    <div class="nf-field">
      <label class="nf-label" for="nf-emergency-contact-form-second_contact_phone">Second contact phone</label>
      <input class="nf-input" id="nf-emergency-contact-form-second_contact_phone" name="second_contact_phone" type="tel" autocomplete="tel">
    </div>
    <div class="nf-field">
      <label class="nf-label" for="nf-emergency-contact-form-medical_notes">Medical notes</label>
      <textarea class="nf-input" id="nf-emergency-contact-form-medical_notes" name="medical_notes" rows="4" placeholder="Allergies, medication or conditions responders should know about"></textarea>
    </div>
  </div>
  <div class="nf-hp" aria-hidden="true"><input type="text" name="_gotcha" tabindex="-1" autocomplete="off"></div>
  <button class="nf-submit" type="submit">Save details</button>
  <p class="nf-error" role="alert" hidden></p>
  <div class="nf-success" role="status" tabindex="-1" hidden>
    <span class="nf-success-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path d="M5 12l5 5l10 -10" pathLength="1"/></svg></span>
    <p class="nf-success-title">Thanks.</p>
    <p class="nf-success-text">Your emergency contacts are saved.</p>
  </div>
</form>
<script>
(function () {
  var form = document.getElementById("nf-emergency-contact-form")
  if (!form || !window.fetch) return
  var started = Date.now()
  var button = form.querySelector('.nf-submit')
  var error = form.querySelector('.nf-error')
  var success = form.querySelector('.nf-success')
  form.addEventListener('submit', function (event) {
    event.preventDefault()
    var data = new FormData(form)
    data.set('_elapsed', String(Date.now() - started))
    var label = button.textContent
    button.disabled = true
    button.textContent = 'Sending...'
    error.hidden = true
    fetch(form.action, {
      method: 'POST',
      headers: { Accept: 'application/json' },
      body: new URLSearchParams(data),
    })
      .then(function (response) {
        return response.json().catch(function () { return {} }).then(function (body) {
          if (!response.ok || !body.ok) throw new Error(body.message || 'Something went wrong. Please try again.')
        })
      })
      .then(function () {
        var redirect = form.getAttribute('data-redirect')
        if (redirect) {
          window.location.href = redirect
          return
        }
        form.style.setProperty('--nf-height', form.offsetHeight + 'px')
        Array.prototype.forEach.call(form.children, function (child) {
          if (child !== success && child.tagName !== 'STYLE') child.hidden = true
        })
        form.classList.add('nf-sent')
        success.hidden = false
        success.focus()
      })
      .catch(function (reason) {
        error.textContent = reason && reason.message ? reason.message : 'Something went wrong. Please try again.'
        error.hidden = false
      })
      .finally(function () {
        button.disabled = false
        button.textContent = label
        if (window.turnstile) window.turnstile.reset()
      })
  })
})()
</script>
```

## Unstyled HTML

Bare markup that picks up your own CSS. It posts without JavaScript and keeps the hidden `_gotcha` field that stops bots.

```html
<form action="https://api.nisuform.com/s/YOUR_FORM_KEY" method="POST">
  <label>
    Full name
    <input name="name" type="text" placeholder="Jane Smith" required>
  </label>
  <label>
    Email
    <input name="email" type="email" placeholder="jane@example.com" required>
  </label>
  <label>
    Emergency contact name
    <input name="contact_name" type="text" placeholder="Sam Smith" required>
  </label>
  <label>
    Relationship to you
    <select name="contact_relationship" required>
      <option value="" disabled selected>Choose one</option>
      <option value="Spouse or partner">Spouse or partner</option>
      <option value="Parent">Parent</option>
      <option value="Child">Child</option>
      <option value="Sibling">Sibling</option>
      <option value="Friend">Friend</option>
      <option value="Other">Other</option>
    </select>
  </label>
  <label>
    Emergency contact phone
    <input name="contact_phone" type="tel" placeholder="+1 555 0100" required>
  </label>
  <label>
    Second contact name
    <input name="second_contact_name" type="text">
  </label>
  <label>
    Second contact phone
    <input name="second_contact_phone" type="tel">
  </label>
  <label>
    Medical notes
    <textarea name="medical_notes" rows="5" placeholder="Allergies, medication or conditions responders should know about"></textarea>
  </label>
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display:none">
  <button type="submit">Save details</button>
</form>
```

## Framework components

### React

```jsx
import { useRef, useState } from 'react'

export function EmergencyContactForm() {
  const renderedAt = useRef(Date.now())
  const [status, setStatus] = useState('idle')

  async function onSubmit(event) {
    event.preventDefault()
    setStatus('sending')
    const data = Object.fromEntries(new FormData(event.currentTarget))
    data._elapsed = String(Date.now() - renderedAt.current)
    const response = await fetch("https://api.nisuform.com/s/YOUR_FORM_KEY", {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
      body: JSON.stringify(data),
    })
    setStatus(response.ok ? 'sent' : 'error')
  }

  if (status === 'sent') return <p>Thanks. Your emergency contacts are saved.</p>

  return (
    <form onSubmit={onSubmit}>
      <label>
        Full name
        <input name="name" type="text" placeholder="Jane Smith" required />
      </label>
      <label>
        Email
        <input name="email" type="email" placeholder="jane@example.com" required />
      </label>
      <label>
        Emergency contact name
        <input name="contact_name" type="text" placeholder="Sam Smith" required />
      </label>
      <label>
        Relationship to you
        <select name="contact_relationship" defaultValue="" required>
          <option value="" disabled>Choose one</option>
          <option value="Spouse or partner">Spouse or partner</option>
          <option value="Parent">Parent</option>
          <option value="Child">Child</option>
          <option value="Sibling">Sibling</option>
          <option value="Friend">Friend</option>
          <option value="Other">Other</option>
        </select>
      </label>
      <label>
        Emergency contact phone
        <input name="contact_phone" type="tel" placeholder="+1 555 0100" required />
      </label>
      <label>
        Second contact name
        <input name="second_contact_name" type="text" />
      </label>
      <label>
        Second contact phone
        <input name="second_contact_phone" type="tel" />
      </label>
      <label>
        Medical notes
        <textarea name="medical_notes" rows={5} placeholder="Allergies, medication or conditions responders should know about"></textarea>
      </label>
      <input type="text" name="_gotcha" tabIndex={-1} autoComplete="off" style={{ display: 'none' }} />
      <button type="submit" disabled={status === 'sending'}>Save details</button>
      {status === 'error' && <p role="alert">Something went wrong. Please try again.</p>}
    </form>
  )
}
```

### Next.js

```jsx
'use client'

import { useRef, useState } from 'react'

export function EmergencyContactForm() {
  const renderedAt = useRef(Date.now())
  const [status, setStatus] = useState('idle')

  async function onSubmit(event) {
    event.preventDefault()
    setStatus('sending')
    const data = Object.fromEntries(new FormData(event.currentTarget))
    data._elapsed = String(Date.now() - renderedAt.current)
    const response = await fetch("https://api.nisuform.com/s/YOUR_FORM_KEY", {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
      body: JSON.stringify(data),
    })
    setStatus(response.ok ? 'sent' : 'error')
  }

  if (status === 'sent') return <p>Thanks. Your emergency contacts are saved.</p>

  return (
    <form onSubmit={onSubmit}>
      <label>
        Full name
        <input name="name" type="text" placeholder="Jane Smith" required />
      </label>
      <label>
        Email
        <input name="email" type="email" placeholder="jane@example.com" required />
      </label>
      <label>
        Emergency contact name
        <input name="contact_name" type="text" placeholder="Sam Smith" required />
      </label>
      <label>
        Relationship to you
        <select name="contact_relationship" defaultValue="" required>
          <option value="" disabled>Choose one</option>
          <option value="Spouse or partner">Spouse or partner</option>
          <option value="Parent">Parent</option>
          <option value="Child">Child</option>
          <option value="Sibling">Sibling</option>
          <option value="Friend">Friend</option>
          <option value="Other">Other</option>
        </select>
      </label>
      <label>
        Emergency contact phone
        <input name="contact_phone" type="tel" placeholder="+1 555 0100" required />
      </label>
      <label>
        Second contact name
        <input name="second_contact_name" type="text" />
      </label>
      <label>
        Second contact phone
        <input name="second_contact_phone" type="tel" />
      </label>
      <label>
        Medical notes
        <textarea name="medical_notes" rows={5} placeholder="Allergies, medication or conditions responders should know about"></textarea>
      </label>
      <input type="text" name="_gotcha" tabIndex={-1} autoComplete="off" style={{ display: 'none' }} />
      <button type="submit" disabled={status === 'sending'}>Save details</button>
      {status === 'error' && <p role="alert">Something went wrong. Please try again.</p>}
    </form>
  )
}
```

### Vue

```vue
<script setup>
import { ref } from 'vue'

const shownAt = Date.now()
const status = ref('idle')

async function onSubmit(event) {
  status.value = 'sending'
  const data = new FormData(event.target)
  data.set('_elapsed', String(Date.now() - shownAt))
  const response = await fetch("https://api.nisuform.com/s/YOUR_FORM_KEY", {
    method: 'POST',
    headers: { Accept: 'application/json' },
    body: data,
  })
  status.value = response.ok ? 'sent' : 'error'
}
</script>

<template>
  <p v-if="status === 'sent'">Thanks. Your emergency contacts are saved.</p>
  <form v-else @submit.prevent="onSubmit">
    <label>
      Full name
      <input name="name" type="text" placeholder="Jane Smith" required>
    </label>
    <label>
      Email
      <input name="email" type="email" placeholder="jane@example.com" required>
    </label>
    <label>
      Emergency contact name
      <input name="contact_name" type="text" placeholder="Sam Smith" required>
    </label>
    <label>
      Relationship to you
      <select name="contact_relationship" required>
        <option value="" disabled selected>Choose one</option>
        <option value="Spouse or partner">Spouse or partner</option>
        <option value="Parent">Parent</option>
        <option value="Child">Child</option>
        <option value="Sibling">Sibling</option>
        <option value="Friend">Friend</option>
        <option value="Other">Other</option>
      </select>
    </label>
    <label>
      Emergency contact phone
      <input name="contact_phone" type="tel" placeholder="+1 555 0100" required>
    </label>
    <label>
      Second contact name
      <input name="second_contact_name" type="text">
    </label>
    <label>
      Second contact phone
      <input name="second_contact_phone" type="tel">
    </label>
    <label>
      Medical notes
      <textarea name="medical_notes" rows="5" placeholder="Allergies, medication or conditions responders should know about"></textarea>
    </label>
    <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display:none">
    <button type="submit" :disabled="status === 'sending'">Save details</button>
    <p v-if="status === 'error'" role="alert">Something went wrong. Please try again.</p>
  </form>
</template>
```

### Svelte

```svelte
<script>
  const shownAt = Date.now()
  let status = $state('idle')

  async function onsubmit(event) {
    event.preventDefault()
    status = 'sending'
    const data = new FormData(event.currentTarget)
    data.set('_elapsed', String(Date.now() - shownAt))
    const response = await fetch("https://api.nisuform.com/s/YOUR_FORM_KEY", {
      method: 'POST',
      headers: { Accept: 'application/json' },
      body: data,
    })
    status = response.ok ? 'sent' : 'error'
  }
</script>

{#if status === 'sent'}
  <p>Thanks. Your emergency contacts are saved.</p>
{:else}
  <form {onsubmit}>
    <label>
      Full name
      <input name="name" type="text" placeholder="Jane Smith" required>
    </label>
    <label>
      Email
      <input name="email" type="email" placeholder="jane@example.com" required>
    </label>
    <label>
      Emergency contact name
      <input name="contact_name" type="text" placeholder="Sam Smith" required>
    </label>
    <label>
      Relationship to you
      <select name="contact_relationship" required>
        <option value="" disabled selected>Choose one</option>
        <option value="Spouse or partner">Spouse or partner</option>
        <option value="Parent">Parent</option>
        <option value="Child">Child</option>
        <option value="Sibling">Sibling</option>
        <option value="Friend">Friend</option>
        <option value="Other">Other</option>
      </select>
    </label>
    <label>
      Emergency contact phone
      <input name="contact_phone" type="tel" placeholder="+1 555 0100" required>
    </label>
    <label>
      Second contact name
      <input name="second_contact_name" type="text">
    </label>
    <label>
      Second contact phone
      <input name="second_contact_phone" type="tel">
    </label>
    <label>
      Medical notes
      <textarea name="medical_notes" rows="5" placeholder="Allergies, medication or conditions responders should know about"></textarea>
    </label>
    <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display:none">
    <button type="submit" disabled={status === 'sending'}>Save details</button>
    {#if status === 'error'}
      <p role="alert">Something went wrong. Please try again.</p>
    {/if}
  </form>
{/if}
```

### Astro

```astro
---
const endpoint = "https://api.nisuform.com/s/YOUR_FORM_KEY"
---

<form action={endpoint} method="POST">
  <label>
    Full name
    <input name="name" type="text" placeholder="Jane Smith" required>
  </label>
  <label>
    Email
    <input name="email" type="email" placeholder="jane@example.com" required>
  </label>
  <label>
    Emergency contact name
    <input name="contact_name" type="text" placeholder="Sam Smith" required>
  </label>
  <label>
    Relationship to you
    <select name="contact_relationship" required>
      <option value="" disabled selected>Choose one</option>
      <option value="Spouse or partner">Spouse or partner</option>
      <option value="Parent">Parent</option>
      <option value="Child">Child</option>
      <option value="Sibling">Sibling</option>
      <option value="Friend">Friend</option>
      <option value="Other">Other</option>
    </select>
  </label>
  <label>
    Emergency contact phone
    <input name="contact_phone" type="tel" placeholder="+1 555 0100" required>
  </label>
  <label>
    Second contact name
    <input name="second_contact_name" type="text">
  </label>
  <label>
    Second contact phone
    <input name="second_contact_phone" type="tel">
  </label>
  <label>
    Medical notes
    <textarea name="medical_notes" rows="5" placeholder="Allergies, medication or conditions responders should know about"></textarea>
  </label>
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display:none">
  <button type="submit">Save details</button>
</form>
```

## When to use it

- Employee onboarding, and the yearly reminder to update details
- Schools, daycares and after-school programs
- Sports clubs, camps, trips and races
- Volunteers, contractors and event staff

## Customize it

### Collect updates by sending the link again

Every submission is saved with the date it was sent. When someone fills in the form again, their newest submission is their current contact, and searching the inbox by name shows both.

### Only ask for medical details you need

Health information is sensitive personal data under laws like the GDPR. If nobody on your side will act on allergies or medication, delete the notes field.

### Tell teams or groups apart

Add `<input type="hidden" name="team" value="Warehouse">` to each copy of the form, or a select field, so every submission shows which group it came from.

### Keep a copy where you need it

Export submissions as CSV on any plan, or on Pro add each one to Google Sheets as it arrives.

## Frequently asked questions

### Is it safe to collect emergency contacts with an online form?

The form posts over HTTPS to Nisuform, and submissions are only visible to members of your team in the dashboard. Every account includes a Data Processing Agreement. Ask only for what you need, and make medical notes optional.

### Can I print this emergency contact form?

This template is an online form, so people fill it in on a phone or computer. To keep a paper copy, export the answers as CSV and print them from a spreadsheet.

### How do people update their emergency contact?

They fill in the form again. Each submission keeps its date, so the newest one for a person is their current contact.

### Can a parent fill it in for a child?

Yes. Change the first label to the child’s name and the email label to the parent’s email, so replies go to the parent.
