Citation Style Formatter — Free APA & MLA Generator HTML CSS JS
Citation Style Formatter · Tools · Plain HTML, CSS & JS · Live preview
Copy & paste
Source Code
<div class="cf-card">
<h3>Citation formatter</h3>
<div class="cf-style" role="radiogroup" aria-label="Citation style">
<button type="button" class="cf-style-btn active" data-style="apa">APA</button>
<button type="button" class="cf-style-btn" data-style="mla">MLA</button>
</div>
<div class="cf-fields">
<label class="cf-field">
<span>Author (full name)</span>
<input type="text" id="cfAuthor" placeholder="Jane A. Smith" value="Jane A. Smith">
</label>
<label class="cf-field">
<span>Title of work</span>
<input type="text" id="cfTitle" placeholder="The Long Thaw" value="The Long Thaw">
</label>
<label class="cf-field">
<span>Publication / site name</span>
<input type="text" id="cfPublication" placeholder="Atlas Review" value="Atlas Review">
</label>
<label class="cf-field">
<span>Year</span>
<input type="text" id="cfYear" placeholder="2024" value="2024">
</label>
<label class="cf-field">
<span>URL</span>
<input type="text" id="cfUrl" placeholder="https://example.com/article" value="https://example.com/the-long-thaw">
</label>
</div>
<div class="cf-output">
<p class="cf-citation" id="cfCitation"></p>
<button type="button" class="cf-copy" id="cfCopy">Copy citation</button>
</div>
</div>*{box-sizing:border-box;margin:0;padding:0}
body{font-family:system-ui,-apple-system,sans-serif;background:#0f1116;color:#e7e9ee;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:32px 20px}
.cf-card{background:#171a21;border:1px solid #272c37;border-radius:16px;padding:24px;width:100%;max-width:440px}
.cf-card h3{font-size:16.5px;font-weight:800;margin-bottom:14px}
.cf-style{display:flex;background:#1e222c;border-radius:10px;padding:3px;margin-bottom:16px}
.cf-style-btn{flex:1;border:none;background:none;padding:9px;border-radius:8px;font-size:13px;font-weight:700;color:#8b93a5;cursor:pointer;transition:background .15s,color .15s}
.cf-style-btn.active{background:#3b82f6;color:#fff}
.cf-fields{display:flex;flex-direction:column;gap:10px;margin-bottom:16px}
.cf-field{display:flex;flex-direction:column;gap:5px}
.cf-field span{font-size:11.5px;font-weight:700;color:#8b93a5;text-transform:uppercase;letter-spacing:.04em}
.cf-field input{border:1.5px solid #272c37;background:#12151b;border-radius:9px;padding:10px 12px;font-size:13.5px;color:#e7e9ee;font-family:inherit;outline:none;transition:border-color .15s}
.cf-field input:focus{border-color:#3b82f6}
.cf-output{background:#12151b;border:1px solid #272c37;border-radius:12px;padding:16px}
.cf-citation{font-size:14px;line-height:1.65;color:#e7e9ee;margin-bottom:12px;word-break:break-word}
.cf-citation i{font-style:italic}
.cf-copy{background:#242938;color:#c9cfdb;border:1px solid #323950;border-radius:8px;padding:9px 14px;font-size:12.5px;font-weight:700;cursor:pointer;transition:background .15s,color .15s}
.cf-copy:hover{background:#2c3244;color:#fff}
.cf-copy.cf-copied{background:#16a34a;border-color:#16a34a;color:#fff}var style = 'apa';
var fields = {
author: document.getElementById('cfAuthor'),
title: document.getElementById('cfTitle'),
publication: document.getElementById('cfPublication'),
year: document.getElementById('cfYear'),
url: document.getElementById('cfUrl'),
};
var citationEl = document.getElementById('cfCitation');
var copyBtn = document.getElementById('cfCopy');
function escapeHtml(s) {
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
}
// "Jane A. Smith" -> "Smith, J. A." (APA: initials only for first/middle names)
function authorApa(full) {
var parts = full.trim().split(/\s+/).filter(Boolean);
if (parts.length === 0) return '';
if (parts.length === 1) return parts[0];
var last = parts.pop();
var initials = parts.map(function (p) { return p.charAt(0).toUpperCase() + '.'; }).join(' ');
return last + ', ' + initials;
}
// "Jane A. Smith" -> "Smith, Jane A." (MLA: full first/middle names kept)
function authorMla(full) {
var parts = full.trim().split(/\s+/).filter(Boolean);
if (parts.length === 0) return '';
if (parts.length === 1) return parts[0];
var last = parts.pop();
return last + ', ' + parts.join(' ');
}
// Titles/sentences don't get a second terminal period if they already end in . ! or ?
function withTerminal(text, punct) {
var t = text.trim();
if (!t) return '';
var last = t.charAt(t.length - 1);
if (last === '.' || last === '!' || last === '?') return t;
return t + punct;
}
// MLA style omits the leading http:// or https:// from URLs.
function stripProtocol(url) {
return url.trim().replace(/^https?:\/\//i, '');
}
function buildApa(v) {
var author = authorApa(v.author);
var year = v.year.trim();
var title = withTerminal(v.title, '.');
var pub = withTerminal(v.publication, '.');
var url = v.url.trim();
var out = '';
if (author) out += escapeHtml(author) + ' ';
if (year) out += '(' + escapeHtml(year) + '). ';
if (title) out += '<i>' + escapeHtml(title) + '</i> ';
if (pub) out += escapeHtml(pub) + ' ';
if (url) out += escapeHtml(url);
return out.trim();
}
function buildMla(v) {
var author = authorMla(v.author);
var year = v.year.trim();
var title = withTerminal(v.title, '.');
var pub = v.publication.trim();
var url = stripProtocol(v.url);
var out = '';
if (author) out += escapeHtml(withTerminal(author, '.')) + ' ';
if (title) out += '"' + escapeHtml(title) + '" ';
if (pub) out += '<i>' + escapeHtml(pub) + '</i>, ';
if (year) out += escapeHtml(year) + ', ';
if (url) out += escapeHtml(url) + '.';
return out.trim();
}
function plainText(html) {
return html.replace(/<i>/g, '').replace(/<\/i>/g, '').replace(/"/g, '"').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
}
function render() {
var v = {
author: fields.author.value,
title: fields.title.value,
publication: fields.publication.value,
year: fields.year.value,
url: fields.url.value,
};
var html = style === 'apa' ? buildApa(v) : buildMla(v);
citationEl.innerHTML = html || 'Fill in the fields above to build a citation.';
copyBtn.classList.remove('cf-copied');
copyBtn.textContent = 'Copy citation';
}
document.querySelector('.cf-style').addEventListener('click', function (e) {
var btn = e.target.closest('.cf-style-btn');
if (!btn) return;
style = btn.dataset.style;
document.querySelectorAll('.cf-style-btn').forEach(function (b) { b.classList.toggle('active', b === btn); });
render();
});
Object.keys(fields).forEach(function (key) {
fields[key].addEventListener('input', render);
});
copyBtn.addEventListener('click', function () {
var text = plainText(citationEl.innerHTML);
var done = function () {
copyBtn.classList.add('cf-copied');
copyBtn.textContent = 'Copied \u2713';
setTimeout(function () {
copyBtn.classList.remove('cf-copied');
copyBtn.textContent = 'Copy citation';
}, 1600);
};
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(done).catch(function () {});
} else {
var ta = document.createElement('textarea');
ta.value = text;
document.body.appendChild(ta);
ta.select();
try { document.execCommand('copy'); done(); } catch (err) {}
document.body.removeChild(ta);
}
});
render();Extend with AI
Take This Snippet Further With AI
The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.
What's included
Features
About this UI Snippet
Citation Style Formatter — Real APA and MLA Punctuation Rules, Not Approximations

Most "citation generator" demos get the easy 80% right and fumble the punctuation that actually matters — where italics go, whether a period sits inside or outside quotation marks, whether the URL keeps its protocol. This snippet builds a genuinely accurate APA and MLA formatter from five structured fields (author, title, publication, year, URL), in plain HTML, CSS, and vanilla JavaScript, with italics represented via CSS font-style since the output is plain text.
APA: the work's title is italicized, not the site
For an online work, APA style (7th edition) italicizes the *title of the work itself* and leaves the publication/site name in plain text: Smith, J. A. (2024). The Long Thaw. Atlas Review. https://…. The author is reduced to last name plus initials — authorApa() splits the full name, pops the last token as the surname, and reduces every remaining token to a capitalized initial. The year sits in parentheses immediately after the author, and the URL is included in full with its protocol, no trailing period.
MLA: the title gets quotes, the publication gets italics — the opposite pairing
MLA style (9th edition) treats the source title as a *part of* its container: it goes in quotation marks, while the container — the publication or site name — is what gets italicized: Smith, Jane A. "The Long Thaw." Atlas Review, 2024, example.com/the-long-thaw. The author keeps full first and middle names rather than reducing to initials (authorMla()), and per current MLA guidance, the URL's http:// or https:// prefix is stripped before it's included — a genuinely easy-to-miss detail this formatter gets right automatically.
Terminal punctuation that respects existing punctuation
A title that already ends in a question mark or exclamation point shouldn't get a second, redundant period after it — withTerminal() checks the last character before deciding whether to append one, in both styles. This is a small rule that a naive "always add a period" implementation gets wrong.
One state, two renderers, no re-typing
The five input fields feed a single v object on every keystroke, and buildApa() / buildMla() are pure functions from that object to a citation string — switching styles re-runs the same field values through the other formatter, so nothing needs re-entering when you compare styles side by side.
Copy button with a real fallback
The copy button uses the modern navigator.clipboard API when available and falls back to a hidden-textarea-plus-execCommand approach otherwise, so it works in older or restricted embedding contexts too.
Customizing it
Add support for multiple authors (APA joins additional authors with &; MLA lists only the first author followed by "et al." for three or more), or extend the field set for journal volume/issue numbers. Pair it with code block for a technical writing toolkit, or a table of contents for a long-form article layout.
Step by step
How to Use
- 1Paste HTML, CSS, and JSA formatter loads with example fields already filled in, showing an APA citation.
- 2Edit the fieldsAuthor, title, publication, year, and URL — the citation updates on every keystroke.
- 3Switch to MLAWatch the punctuation invert: the title moves into quotes and the publication becomes italicized.
- 4Click "Copy citation"The plain-text citation (no HTML markup) is copied to your clipboard.
- 5Try edge casesA single-word author name or a title ending in "?" both format correctly without extra punctuation.
- 6Extend for your needsAdd multi-author support or journal-specific fields like volume and issue.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
In APA, the title of the work is italicized and the publication/site name is plain text, with the author reduced to last name plus initials and the year in parentheses right after the author. In MLA, that pairing inverts: the title goes in quotation marks and the publication is italicized instead, the author keeps full first and middle names, and the year moves later in the citation, after the publication.
MLA style specifically instructs writers to omit the leading http:// or https:// from a URL in a Works Cited entry, so this formatter strips it automatically for MLA output via stripProtocol(). APA style keeps the URL exactly as entered, protocol included, since APA references are meant to be directly clickable/functional as given.
withTerminal() inspects the last character of the title (or author string) before deciding whether to append a period — if the text already ends in a period, question mark, or exclamation point, nothing extra is added. Without this check, a title like "What Is Justice?" would incorrectly render as "What Is Justice?." with a redundant trailing period.
APA joins two authors with an ampersand (Smith, J. A., & Lee, K.) and switches to "et al." after 20 authors; MLA lists only the first author in "Last, First" form followed by ", et al." once there are three or more authors, but keeps both names spelled out in full for exactly two. You would extend the author field to accept multiple names (or add repeatable fields) and branch authorApa()/authorMla() on the count.
Hold the five field values in component state and recompute the citation with a memoized/computed value keyed to those fields and the selected style — buildApa() and buildMla() are already pure functions of a plain data object, so they port unchanged into any framework; only the input bindings and the copy button's DOM access change.