kiltel
v3.0.0
Published
Universal international phone input with flag icons and country code sync.
Maintainers
Readme
Kiltel.js — Lightweight, Modern International Phone Input
Beautiful flag + dial-code selector, no jQuery, no paid APIs. MIT licensed.
✨ Features
- 🌍 Flag + country code dropdown (keyboard + mouse)
- 🔎 Search by country name / ISO code / dial code
- 🎨 Pure CSS styling — fits Bootstrap or custom UIs
- 🧩 Works with server-rendered pages (EJS, Pug) and SPA frameworks
- ✅ Optional validation via
intl-tel-input(auto-loaded when enabled) - 🔢 Outputs three values: full (
+<dial><national>), country_code (+<dial>), contact (<national>) - 📦 Restrict list (only/exclude) and set preferred countries
- 🧠 Handles prefilled values, autofill, and paste
- 🛡️ No tracking, no paid APIs, MIT License
Table of Contents
- CDN Quick Start
- HTML Markup (Required Structure)
- Attributes Reference
- What Gets Submitted
- Enable Validation (Optional)
- Multiple Fields on the Same Page
- React/SPA Usage
- Styling & Theming
- Accessibility
- Advanced Notes
- Troubleshooting / FAQ
- Credits
- License
CDN Quick Start
Include the CSS and JS from jsDelivr:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/kiltel.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/kiltel.min.js"></script>Kiltel auto-initializes on
DOMContentLoaded.
You can also callwindow.kiltelInit()manually if you inject HTML later (e.g., via AJAX).
HTML Markup (Required Structure)
The main input and its two hidden fields must be inside a wrapper with class
kiltel-phone-wrap.
The block below is shown as-is in README (inside a fenced code block) so it renders exactly:
<div class="form-group row width-50">
<label class="col-5 control-label">Contact No.</label>
<div class="kiltel-phone-wrap col-6">
<button type="button" class="kiltel-country-trigger"></button>
<input
type="tel"
class="form-control"
data-kilvish-tel
id="kilvishcontact"
name="full_contact"
placeholder="Enter mobile number"
data-kiltel-init="IT"
data-kiltel-validation="yes"
data-kilvish-only="IN,IT,US"
data-kilvish-preferred="IN"
required
readonly
value="+393381112223"
>
Prefilled/readonly for demo!
<span class="fa fa-fw fa-phone" style="position: absolute; top: 10px; right: 25px; cursor: pointer;"></span>
<input type="hidden" id="country_code" name="country_code">
<input type="hidden" id="contact" name="contact">
</div>
<div id="kiltel-error" style="color:red; font-size:0.93em; margin-top:5px;"></div>
</div>Notes
- The
button.kiltel-country-triggeris either auto-created or you can place it manually (as above). - For readonly demo, keep
readonlyand a samplevalue. For real forms, removereadonly.
Attributes Reference
| Attribute | Description | Example |
|---|---|---|
| data-kilvish-tel | Activates Kiltel for this input | (required) |
| data-kiltel-init | Initial country (ISO code) | "IT", "US", "IN" |
| data-kiltel-validation | Validates number (loads intl-tel-input automatically) | "yes" |
| data-kilvish-only | Show only these countries (comma-separated ISO codes) | "IN,US,IT" |
| data-kilvish-exclude | Exclude these countries from dropdown | "CN,RU" |
| data-kilvish-preferred | Pin these at top of list | "IN,US" |
Hidden fields inside .kiltel-phone-wrap
<input type="hidden" name="country_code">— will contain+<dial>(e.g.,+91)<input type="hidden" name="contact">— will contain national digits (e.g.,1234567890)
What Gets Submitted
- Main input (
name="full_contact"in the example) shows+<dial><national>(e.g.,+911234567890). - Hidden
country_code→+<dial>(e.g.,+91) - Hidden
contact→ national number (e.g.,1234567890)
Kiltel keeps these in sync as the user types, pastes, or switches country.
Enable Validation (Optional)
Add data-kiltel-validation="yes" on the input to enable validation-on-blur.
Kiltel dynamically loads [email protected] (and utils.js) — no extra tags needed.
- Unknown/invalid country code → shows
"Unknown country code!" - Invalid format for selected country → shows
"Invalid phone number for <Country>"
Error is written into an element with id kiltel-error if present; otherwise one is created next to the input wrapper.
Multiple Fields on the Same Page
Just repeat the wrapper block:
<div class="kiltel-phone-wrap">
<button type="button" class="kiltel-country-trigger"></button>
<input type="tel" class="form-control" data-kilvish-tel name="billing_phone">
<input type="hidden" name="billing_country_code">
<input type="hidden" name="billing_contact">
</div>
<div class="kiltel-phone-wrap">
<button type="button" class="kiltel-country-trigger"></button>
<input type="tel" class="form-control" data-kilvish-tel name="shipping_phone" data-kilvish-only="IN,US" data-kilvish-preferred="IN">
<input type="hidden" name="shipping_country_code">
<input type="hidden" name="shipping_contact">
</div>Kiltel guards against double-initialization automatically.
React/SPA Usage
If the field is rendered after page load, call window.kiltelInit() once the DOM is updated:
useEffect(() => {
// render phone input DOM first, then:
window.kiltelInit?.();
}, []);For frameworks with virtual DOM, prefer uncontrolled inputs or refs; Kiltel manipulates the real input value (.value).
Styling & Theming
Kiltel ships with a minimalist CSS. Common hooks:
.kiltel-phone-wrap— container (setposition:relativein your form CSS if needed).kiltel-country-trigger— flag/dropdown button.kiltel-country-list— popup list container.kiltel-country-option— each option (active option has.active).kiltel-country-search— search input inside the dropdown
You can safely override sizes, fonts, borders, shadows, etc.
Accessibility
- Trigger is a real
<button>— keyboard & screen-reader friendly - Search input focuses automatically when the dropdown opens
- You can add
aria-labelon the trigger if needed
Advanced Notes
- Restrict candidates: Kiltel will only match country by number within the available (allowed) list if you used
data-kilvish-onlyordata-kilvish-exclude. - IP-based default: If
data-kiltel-initis not provided and the input is empty, Kiltel attempts to set the country based onhttps://ipapi.co/json/(best-effort). - Prefilled values: If the input already contains a
+<dial>...value on load, Kiltel sets the correct flag without overwriting the text (read-only friendly).
Troubleshooting / FAQ
The dropdown width looks off
Kiltel auto-fits the dropdown to the wrapper width. Ensure .kiltel-phone-wrap (or the input) has a width in your layout.
The flag doesn’t show
We load flags from jsDelivr: https://cdn.jsdelivr.net/npm/kiltel@latest/svg/<country>.svg.
Check network access or override via CSS if you host flags yourself.
Validation doesn’t run
Ensure the input has data-kiltel-validation="yes". Kiltel auto-loads [email protected] and its utils.js at runtime.
I need read-only view
Keep the input readonly with a prefilled value="+<dial><national>". Kiltel will render the flag and dial code correctly.
Credits
- Author: Kilvish (Vasu Birla) — https://github.com/Vasu-Birla / mailto:[email protected]
- Idea, code & maintenance: Kilvish Birla, with community feedback and UX tuning
- Special thanks: intl-tel-input — used optionally for validation only
- Community: Contributors, testers, and developers who improve Kiltel
License
MIT — Fork, remix, and use in commercial projects. No attribution required (but appreciated!).
