Hezká čeština na webu začíná drobnostmi. Jednou z nich jsou jednoznakové předložky a spojky, které by neměly zůstávat na konci řádku. Připravil jsem krátký kód pro WordPress, který to řeší čistě při výstupu do HTML – bez zásahu do obsahu a bez ztráty výkonu.
Proč to řešit
V češtině je nehezké (a typograficky nesprávné), když na konci řádku zůstane osamocené „a“, „v“, „s“ apod. Pevná mezera mezi jednoznakovým slovem a následujícím slovem zabrání zlomu řádku na tomto místě. Prohlížeč pak slova udrží na jednom řádku.
Co přesně uděláme
Při renderování obsahu (bez zásahu do databáze) projdeme text a nahradíme:
a→a i→i k→k o→o s→s u→u v→v z→z
Funguje to v běžných blocích Gutenbergu (odstavce, nadpisy, seznamy…), i v nadpisech a výpisech. Nezasahujeme do HTML tagů ani atributů, takže nerozbijeme odkazy, obrázky, apod.
Implementace (zkopíruj & vlož)
Kód vlož do functions.php child šablony nebo do správce snippetů (např. WPCode). Případně můžeš udělat vlastní plugin.
/**
* Pevná mezera po jednoznakových slovech (a, i, k, o, s, u, v, z).
* Funguje v obsahu, nadpisech, výpisech i widgetech. Bez zásahu do HTML tagů/atributů.
*/
function cz_nbsp_single_letters_apply($html){
if (empty($html)) return $html;
// Rozdělíme na HTML tagy a text, upravujeme jen text
$parts = preg_split('/(<[^>]+>)/u', $html, -1, PREG_SPLIT_DELIM_CAPTURE);
foreach ($parts as $i => $part){
if ($part === '' || $part[0] === '<') continue;
// mezera po jednoznakovém slově → pevná mezera
// začátek řádku nebo whitespace, pak [AaIiKkOoSsUuVvZz], pak mezera před neprázdným znakem
$parts[$i] = preg_replace(
'/(?<=^|\s)([AaIiKkOoSsUuVvZz])\s+(?=\S)/u',
'$1 ',
$part
);
}
return implode('', $parts);
}
// Aplikace na hlavní výstupy
add_filter('the_content', 'cz_nbsp_single_letters_apply', 12);
add_filter('the_title', 'cz_nbsp_single_letters_apply', 12);
add_filter('get_the_excerpt', 'cz_nbsp_single_letters_apply', 12);
add_filter('widget_text', 'cz_nbsp_single_letters_apply', 12);
// Volitelně i na renderované bloky (lepší pokrytí popisků, seznamů apod.)
add_filter('render_block', function($content, $block){
if (!isset($block['blockName'])) return $content;
$targets = [
'core/paragraph','core/heading','core/list','core/quote','core/pullquote',
'core/table','core/verse','core/media-text','core/image','core/gallery'
];
return in_array($block['blockName'], $targets, true)
? cz_nbsp_single_letters_apply($content)
: $content;
}, 12, 2);
Proč právě takto (a ne CSS/JS)
- CSS to neumí – line-breaky neovlivníte selektivně jen po daných písmenech.
- JS by to šlo, ale zbytečně tím zhoršíte výkon a SEO (DOM manipulace po načtení).
- PHP filtr je čisté a rychlé řešení přímo ve fázi renderu.
Kompatibilita a výkon
Řešení je otestované na blocích Gutenbergu a funguje i v nadpisech, výpisech a widgetech. Díky tomu, že při zpracování oddělujeme HTML tagy od textu, zůstávají značky a atributy nedotčené, takže se nerozbíjejí odkazy ani jiné prvky. Použitý regulární výraz je jednoduchý, proto je dopad na výkon zanedbatelný i u delších článků.
Tipy a výjimky
Pravidlo míří na češtinu — na anglických či německých verzích webu ho obvykle nechcete. Snadno ho proto podmíníte jazykem (Polylang/WMPL konstanta, případně get_locale()). Pokud potřebujete úpravu vynechat v některých blocích, stačí v hooku render_block upravit pole $targets a nechat v něm jen ty, kde má zásah probíhat. Obsah v administraci zůstává beze změny, protože kód běží až na frontendu při renderu stránky. A ještě detail: vzor je case-insensitive, takže funguje i na velká písmena typu „A“ nebo „I“.
Časté dotazy (FAQ)
Rozbije to odkazy?
Ne. Úprava probíhá jen v textových uzlech, ne v HTML atributech.
Proč nepoužít existující plugin?
Současné pluginy v repozitáři už většinou nefungují, toto je aktuálně otestované řešení.
Co když chci tenčí (úzkou) pevnou mezeru?
Prohlížeče běžně pracují s (U+00A0). „Úzká“ pevná mezera (U+202F) má horší podporu – nedoporučuji pro běžné weby.


Hmmm, hezké řešení, rozhodně vyzkouším. Mám hned několik webů, kde to potřebuji vyřešit. Díky.