Domma Flags
Nation flags as crisp, scalable inline SVG - keyed by ISO code, themable into rectangular, rounded, square or circular shapes. An opt-in module. Click any flag to copy.
One flag, four shapes
<div class="flag-shapes-demo" id="shapes-demo"></div>/**
* One flag, four shapes - from public/showcase/flags.
*/
export function mount(root) {
const shapesHost = $(root).find('#shapes-demo');
['rect', 'rounded', 'square', 'circle'].forEach(shape => {
const fig = document.createElement('figure');
fig.appendChild(FL.render('gb', {size: 72, shape, border: true}));
const cap = document.createElement('figcaption');
cap.textContent = shape;
fig.appendChild(cap);
shapesHost.append(fig);
});
}<div class="flex flex-wrap items-center gap-3 mb-4 sx-gallery-controls">
<input type="text" class="flag-search-input form-input" id="search" placeholder="Search by name or code…" aria-label="Search flags">
<div class="flex gap-2 items-center">
<label class="text-sm opacity-75">Shape</label>
<select id="shape" class="form-select" style="width:auto" aria-label="Flag shape">
<option value="rect">Rectangular</option>
<option value="rounded">Rounded</option>
<option value="square">Square</option>
<option value="circle">Circle</option>
</select>
<label class="text-sm opacity-75 ml-2">Size</label>
<select id="size" class="form-select" style="width:auto" aria-label="Flag size">
<option value="32">32</option>
<option value="48" selected="">48</option>
<option value="64">64</option>
</select>
</div>
</div>
<div id="gallery"></div>
<div class="flag-no-results" id="no-results" style="display:none">No flags match your search.</div>/**
* One flag, four shapes - from public/showcase/flags.
*/
export function mount(root) {
// ---- Gallery ----
const regions = FL.listRegions();
let currentShape = 'rect';
let currentSize = 48;
function renderGallery(query = '') {
const gallery = $(root).find('#gallery');
gallery.html('');
const matches = query ? FL.search(query) : null;
let shown = 0;
_.each(regions, (meta, key) => {
const codes = meta.codes.filter(c => !matches || matches.includes(c));
if (!codes.length) {
return;
}
shown += codes.length;
const title = document.createElement('h2');
title.className = 'flag-region-title';
title.textContent = meta.name;
gallery.append(title);
const grid = document.createElement('div');
grid.className = 'flag-grid';
codes.forEach(code => {
const cell = document.createElement('div');
cell.className = 'flag-cell';
cell.appendChild(FL.render(code, {size: currentSize, shape: currentShape, border: true}));
const name = document.createElement('div');
name.className = 'flag-name';
name.textContent = FL.name(code);
const cd = document.createElement('div');
cd.className = 'flag-code';
cd.textContent = code;
cell.append(name, cd);
$(cell).on('click', () => copy(code));
grid.appendChild(cell);
});
gallery.append(grid);
});
$(root).find('#no-results').css('display', shown ? 'none' : 'block');
}
function copy(code) {
navigator.clipboard.writeText(`data-flag="${code}"`).then(() => {
E.toast(`Copied: ${code}`, {type: 'success', position: 'bottom-center', duration: 1800});
});
}
// Controls
let t;
$(root).find('#search').on('input', function () {
clearTimeout(t);
const v = $(this).val();
t = setTimeout(() => renderGallery(v), 180);
});
$(root).find('#shape').on('change', function () {
currentShape = $(this).val();
renderGallery($(root).find('#search').val());
});
$(root).find('#size').on('change', function () {
currentSize = parseInt($(this).val(), 10);
renderGallery($(root).find('#search').val());
});
// Initial render
renderGallery();
}Usage
HTML data attributes
<!-- after domma.min.js -->
<script src="dist/domma-flags.min.js"></script>
<span data-flag="gb"></span>
<span data-flag="jp" data-flag-shape="circle"
data-flag-size="48" data-flag-border></span>
<script>FL.scan();</script>
JavaScript API
// Render an SVG element
const svg = FL.render('fr', { size: 48, shape: 'rounded' });
document.body.appendChild(svg);
// Inject into a target
FL.inject('#country', 'de', { shape: 'circle', border: true });
// Search & list
FL.search('united'); // ['gb', 'us', 'ae']
FL.list('europe'); // ['gb', 'fr', 'de', ...]
FL.name('br'); // 'Brazil'
// Register your own / override
FL.register('eu', { name: 'European Union', region: 'europe',
bg: '#003399',
overlays: [{ type: 'star', cx: 30, cy: 20, r: 4, fill: '#FFCC00' }] });
Tutorial: a country picker
// Build options from the registry, sorted by name
const codes = _.sortBy(FL.list(), c => FL.name(c));
codes.forEach(code => {
$('#country-picker').append(
`<option value="${code}">${FL.name(code)}</option>`
);
});
// React to selection
$('#country-picker').on('change', function () {
const code = $(this).val();
FL.inject('#picker-flag', code,
{ size: 40, shape: 'rounded', border: true, position: 'replace' });
$('#picker-name').text(FL.name(code));
$('#picker-code').text(code.toUpperCase());
});
<div class="row">
<div class="col-5">
<div class="card">
<div class="card-body">
<label class="d-block mb-2 font-semibold">Choose a country</label>
<select id="country-picker" class="dm-select w-full"></select>
<div class="d-flex align-items-center gap-3 mt-4">
<span id="picker-flag"></span>
<div>
<div id="picker-name" class="font-semibold"></div>
<code id="picker-code" class="text-sm opacity-65"></code>
</div>
</div>
</div>
</div>
</div>
<div class="col-7">
<pre class="code-block language-javascript"><code>// Build options from the registry, sorted by name
const codes = _.sortBy(FL.list(), c => FL.name(c));
codes.forEach(code => {
$('#country-picker').append(
`<option value="${code}">${FL.name(code)}</option>`
);
});
// React to selection
$('#country-picker').on('change', function () {
const code = $(this).val();
FL.inject('#picker-flag', code,
{ size: 40, shape: 'rounded', border: true, position: 'replace' });
$('#picker-name').text(FL.name(code));
$('#picker-code').text(code.toUpperCase());
});</code></pre>
</div>
</div>/**
* Tutorial: a country picker - from public/showcase/flags.
*/
export function mount(root) {
// ---- Tutorial picker ----
_.sortBy(FL.list(), c => FL.name(c)).forEach(code => {
$(root).find('#country-picker').append(`<option value="${code}">${FL.name(code)}</option>`);
});
function updatePicker() {
const code = $(root).find('#country-picker').val();
FL.inject(root.querySelector('#picker-flag'), code, {size: 40, shape: 'rounded', border: true, position: 'replace'});
$(root).find('#picker-name').text(FL.name(code));
$(root).find('#picker-code').text(code.toUpperCase());
}
$(root).find('#country-picker').on('change', updatePicker);
updatePicker();
}