🔍

ᏖᏬᏒᏰᎧᏩᏝᎥᎮ’Ꮥ ᏅᏬᎥᏟᏦ ᏩᏗᏁᏟᎩ ᏩᎧᏁᏖ ᎶᏋᏁᏋᏒᏗᏖᎧᏒ

This is a first attempt to create a custom fancy font generator. Enter some text and the code will use alternative Unicode letters.

This is a first attempt to create a custom fancy font generator. Enter some text and the code will use alternative Unicode letters. This quick tool also has a small „variation“ feature – try it out if you like a style. I also tried to mix some Runic symbols in the selection. This is all experimental. Enjoy the ONLINE DEMO or just take this code 🙂

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ᏖᏬᏒᏰᎧᏩᏝᎥᎮ'Ꮥ ᏅᏬᎥᏟᏦ ᏩᏗᏁᏟᎩ ᏩᎧᏁᏖ ᎶᏋᏁᏋᏒᏗᏖᎧᏒ</title>
    <!-- Tailwind CSS CDN für einfaches Styling -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- Inter Font von Google Fonts -->
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
    <style>
        body {
            font-family: 'Inter', sans-serif;
            background-color: #f0f4f8; /* Heller blaugrauer Hintergrund */
            color: #334155; /* Dunklerer Text */
        }
        /* Benutzerdefinierte Scrollleiste für den Ausgabebereich */
        .output-scroll-area::-webkit-scrollbar {
            width: 8px;
        }
        .output-scroll-area::-webkit-scrollbar-track {
            background: #e2e8f0;
            border-radius: 10px;
        }
        .output-scroll-area::-webkit-scrollbar-thumb {
            background: #94a3b8;
            border-radius: 10px;
        }
        .output-scroll-area::-webkit-scrollbar-thumb:hover {
            background: #64748b;
        }
        /* Stil für die Nachrichtenbox */
        .message-box {
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            background-color: #34d399; /* Grün für Erfolg */
            color: white;
            padding: 12px 20px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
            z-index: 1000;
            opacity: 0;
            transition: opacity 0.3s ease-in-out;
        }
        .message-box.show {
            opacity: 1;
        }
        .vary-button {
            transition: all 0.2s ease-in-out;
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); /* Leichter Schatten für weiße Buttons */
        }
        .vary-button:hover {
            transform: translateY(-1px);
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }
        .vary-button:active {
            transform: translateY(0);
            box-shadow: none;
        }
    </style>
</head>
<body class="flex flex-col items-center justify-center min-h-screen py-8 px-4 sm:px-6 lg:px-8">
    <div class="message-box" id="messageBox"></div>

    <div class="bg-white p-6 rounded-xl shadow-2xl w-full max-w-4xl space-y-6">
        <div class="flex flex-col sm:flex-row gap-3">
            <input
                type="text"
                id="inputText"
                placeholder="Geben Sie hier Ihren Text ein..."
                class="flex-grow p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-base shadow-sm"
                maxlength="100"
            >
            <button
                id="generateButton"
                class="px-5 py-2 bg-white text-gray-700 font-semibold rounded-lg shadow-md hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition duration-200 ease-in-out text-base"
            >
                Generieren
            </button>
        </div>

        <div id="variationsHeaderContainer" class="flex flex-col gap-2 mt-4 pt-2 hidden">
            <h2 class="text-xl font-bold text-gray-800 text-center">Variationen</h2>
        </div>

        <div id="outputContainer" class="flex flex-col gap-4 mt-6 max-h-[60vh] overflow-y-auto pr-2 output-scroll-area">
            <!-- Fancy Fonts werden hier angezeigt -->
            <p class="text-gray-500 text-center">Geben Sie etwas ein und klicken Sie auf 'Generieren', um die Magie zu sehen!</p>
        </div>
    </div>

    <script>
        // Hilfsfunktion zum Anzeigen von Nachrichten
        function showMessage(message, type = 'success') {
            const messageBox = document.getElementById('messageBox');
            messageBox.textContent = message;
            messageBox.className = 'message-box show';
            if (type === 'success') {
                messageBox.style.backgroundColor = '#34d399'; // Grün
            } else if (type === 'error') {
                messageBox.style.backgroundColor = '#ef4444'; // Rot
            }
            setTimeout(() => {
                messageBox.className = 'message-box';
            }, 3000);
        }

        const FONT_TYPES = {
            CHAR_SUBSTITUTION: 'char_substitution'
        };

        // Mappings für verschiedene Fancy Fonts (alle CHAR_SUBSTITUTION)
        const FONT_MAPS = [
            // --- Benutzer-Beispiele zuerst ---
            {
                type: FONT_TYPES.CHAR_SUBSTITUTION, // Canadian Aboriginal Syllabics Lookalikes (ausgewählte, visuelle Übereinstimmung)
                map: {
                    'a': 'ᗩ', 'b': 'ᗷ', 'c': 'ᑢ', 'd': 'ᑐ', 'e': 'ᘿ', 'f': 'ᖬ', 'g': 'ᘜ', 'h': 'ᕼ', 'i': 'ᓰ', 'j': 'ᒍ', 'k': 'ᖽᐸ', 'l': 'ᒪ', 'm': 'ᗰ', 'n': 'ᘉ', 'o': 'ᓍ', 'p': 'ᕵ', 'q': 'ᑫ', 'r': 'ᖇ', 's': 'S', 't': 'ᖶ', 'u': 'ᑘ', 'v': 'ᐯ', 'w': 'ᗯ', 'x': '᙮', 'y': 'ᖻ', 'z': 'ᗣ',
                    'A': 'ᗩ', 'B': 'ᗷ', 'C': 'ᑢ', 'D': 'ᑐ', 'E': 'ᘿ', 'F': 'ᖬ', 'G': 'ᘜ', 'H': 'ᕼ', 'I': 'ᓰ', 'J': 'ᒍ', 'K': 'ᖽᐸ', 'L': 'ᒪ', 'M': 'ᗰ', 'N': 'ᘉ', 'O': 'ᓍ', 'P': 'ᕵ', 'Q': 'ᑫ', 'R': 'ᖇ', 'S': 'S', 'T': 'ᖶ', 'U': 'ᑘ', 'V': 'ᐯ', 'W': 'ᗯ', 'X': '᙮', 'Y': 'ᖻ', 'Z': 'ᗣ',
                    ' ': ' '
                }
            },
            {
                type: FONT_TYPES.CHAR_SUBSTITUTION, // Mixed Script (Thai, Hebrew, Cyrillic, Armenian - รקคгкєг)
                map: {
                    'a': 'ค', 'b': '๒', 'c': 'ς', 'd': '๔', 'e': 'є', 'f': 'Ŧ', 'g': 'ﻮ', 'h': 'ђ', 'i': 'เ', 'j': 'ן', 'k': 'к', 'l': 'l', 'm': '๓', 'n': 'ภ', 'o': '๏', 'p': 'ק', 'q': 'ợ', 'r': 'г', 's': 'ร', 't': 'Շ', 'u': 'ย', 'v': 'ש', 'w': 'ฬ', 'x': 'א', 'y': 'ץ', 'z': 'չ',
                    'A': 'ค', 'B': '๒', 'C': 'ς', 'D': '๔', 'E': 'є', 'F': 'Ŧ', 'G': 'ﻮ', 'H': 'ђ', 'I': 'เ', 'J': 'ן', 'K': 'к', 'L': 'l', 'M': '๓', 'N': 'ภ', 'O': '๏', 'P': 'ק', 'Q': 'ợ', 'R': 'г', 'S': 'ร', 'T': 'Շ', 'U': 'ย', 'V': 'ש', 'W': 'ฬ', 'X': 'א', 'Y': 'ץ', 'Z': 'չ',
                    ' ': ' '
                }
            },
            {
                type: FONT_TYPES.CHAR_SUBSTITUTION, // Cherokee Script (ᏕᎮᏗᏒᏦᏋᏒ)
                map: {
                    'a': 'Ꮧ', 'b': 'Ᏸ', 'c': 'Ꮯ', 'd': 'Ꮄ', 'e': 'Ꮛ', 'f': 'Ꮹ', 'g': 'Ꮆ', 'h': 'Ꮋ', 'i': 'Ꭵ', 'j': 'Ꮷ', 'k': 'Ꮶ', 'l': 'Ꮭ', 'm': 'Ꮇ', 'n': 'Ꮑ', 'o': 'Ꭷ', 'p': 'Ꭾ', 'q': 'Ꮕ', 'r': 'Ꮢ', 's': 'Ꮥ', 't': 'Ꮦ', 'u': 'Ꮼ', 'v': 'Ꮩ', 'w': 'Ꮹ', 'x': 'Ꮿ', 'y': 'Ꭹ', 'z': 'Ꮓ',
                    'A': 'Ꮧ', 'B': 'Ᏸ', 'C': 'Ꮯ', 'D': 'Ꮄ', 'E': 'Ꮛ', 'F': 'Ꮹ', 'G': 'Ꮆ', 'H': 'Ꮋ', 'I': 'Ꭵ', 'J': 'Ꮷ', 'K': 'Ꮶ', 'L': 'Ꮭ', 'M': 'Ꮇ', 'N': 'Ꮑ', 'O': 'Ꭷ', 'P': 'Ꭾ', 'Q': 'Ꮕ', 'R': 'Ꮢ', 'S': 'Ꮥ', 'T': 'Ꮦ', 'U': 'Ꮼ', 'V': 'Ꮩ', 'W': 'Ꮹ', 'X': 'Ꮿ', 'Y': 'Ꭹ', 'Z': 'Ꮓ',
                    ' ': ' '
                }
            },
            {
                type: FONT_TYPES.CHAR_SUBSTITUTION, // Georgian Lookalikes (selektiert, visuelle Übereinstimmung)
                map: {
                    'a': 'Ⴀ', 'b': 'Ⴁ', 'c': 'Ⴍ', 'd': 'Ⴃ', 'e': 'Ⴄ', 'f': 'Ⴔ', 'g': 'Ⴂ', 'h': 'Ⴠ', 'i': 'Ⴈ', 'j': 'Ⴟ', 'k': 'Ⴉ', 'l': 'Ⴊ', 'm': 'Ⴋ', 'n': 'Ⴌ', 'o': 'Ⴍ', 'p': 'Ⴎ', 'q': 'Ⴢ', 'r': 'Ⴐ', 's': 'Ⴑ', 't': 'Ⴒ', 'u': 'Ⴓ', 'v': 'Ⴜ', 'w': 'Ⴗ', 'x': 'Ⴜ', 'y': 'Ⴡ', 'z': 'Ⴏ',
                    'A': 'Ⴀ', 'B': 'Ⴁ', 'C': 'Ⴍ', 'D': 'Ⴃ', 'E': 'Ⴄ', 'F': 'Ⴔ', 'G': 'Ⴂ', 'H': 'Ⴠ', 'I': 'Ⴈ', 'J': 'Ⴟ', 'K': 'Ⴉ', 'L': 'Ⴊ', 'M': 'Ⴋ', 'N': 'Ⴌ', 'O': 'Ⴍ', 'P': 'Ⴎ', 'Q': 'Ⴢ', 'R': 'Ⴐ', 'S': 'Ⴑ', 'T': 'Ⴒ', 'U': 'Ⴓ', 'V': 'Ⴜ', 'W': 'Ⴗ', 'X': 'Ⴜ', 'Y': 'Ⴡ', 'Z': 'Ⴏ',
                    ' ': ' '
                }
            },
            {
                type: FONT_TYPES.CHAR_SUBSTITUTION, // Runic Lookalikes (selected characters from Elder Futhark)
                map: {
                    'a': 'ᚨ', 'b': 'ᛒ', 'c': 'ᚳ', 'd': 'ᛞ', 'e': 'ᛖ', 'f': 'ᚠ', 'g': 'ᚷ', 'h': 'ᚺ', 'i': 'ᛁ', 'j': 'ᛃ', 'k': 'ᚴ', 'l': 'ᛚ', 'm': 'ᛗ', 'n': 'ᚾ', 'o': 'ᛟ', 'p': 'ᛈ', 'q': 'ᚦ', 'r': 'ᚱ', 's': 'ᛋ', 't': 'ᛏ', 'u': 'ᚢ', 'v': 'ᚹ', 'w': 'ᚹ', 'x': 'ᛜ', 'y': 'ᚣ', 'z': 'ᛉ',
                    'A': 'ᚨ', 'B': 'ᛒ', 'C': 'ᚳ', 'D': 'ᛞ', 'E': 'ᛖ', 'F': 'ᚠ', 'G': 'ᚷ', 'H': 'ᚺ', 'I': 'ᛁ', 'J': 'ᛃ', 'K': 'ᚴ', 'L': 'ᛚ', 'M': 'ᛗ', 'N': 'ᚾ', 'O': 'ᛟ', 'P': 'ᛈ', 'Q': 'ᚦ', 'R': 'ᚱ', 'S': 'ᛋ', 'T': 'ᛏ', 'U': 'ᚢ', 'V': 'ᚹ', 'W': 'ᚹ', 'X': 'ᛜ', 'Y': 'ᚣ', 'Z': 'ᛉ',
                    ' ': ' '
                }
            }
        ];

        // Funktion zum Konvertieren von Text basierend auf einer bestimmten Zuordnung
        function convertText(text, fontMap) {
            let convertedText = '';
            const normalizedText = text.normalize('NFD');

            for (let i = 0; i < normalizedText.length; i++) {
                const char = normalizedText[i];
                // Stellen Sie sicher, dass keine kombinierenden Diakritika als Basiszeichen behandelt werden
                if (char.length > 1 && /[\u0300-\u036F]/.test(char)) {
                    convertedText += char;
                    continue;
                }

                const lowerChar = char.toLowerCase();
                const upperChar = char.toUpperCase();

                if (fontMap.map[char]) {
                    convertedText += fontMap.map[char];
                } else if (fontMap.map[lowerChar] && char === upperChar) {
                    convertedText += fontMap.map[lowerChar].toUpperCase();
                } else {
                    convertedText += char; // Zeichen unverändert lassen, wenn nicht in der Map
                }
            }
            return convertedText.normalize('NFC');
        }

        // Funktion zum Generieren von Variationen eines Zeichenersetzungs-Stils
        function generateCharSubstitutionVariations(originalText, count = 5) {
            const variations = [];
            const charSubMaps = FONT_MAPS.filter(f => f.type === FONT_TYPES.CHAR_SUBSTITUTION);

            for (let i = 0; i < count; i++) {
                let variedText = '';
                for (let j = 0; j < originalText.length; j++) {
                    const char = originalText[j];
                    if (char === ' ') {
                        variedText += ' ';
                        continue;
                    }
                    const randomMapIndex = Math.floor(Math.random() * charSubMaps.length);
                    const selectedFontMap = charSubMaps[randomMapIndex];

                    variedText += convertText(char, selectedFontMap);
                }
                variations.push({
                    type: FONT_TYPES.CHAR_SUBSTITUTION,
                    map: {},
                    convertedText: variedText
                });
            }
            return variations;
        }

        // Funktion zum Anzeigen der generierten Fancy Fonts und deren Buttons
        function displayFancyFonts(inputText, isVariationMode = false, originalFontDetails = null) {
            const outputContainer = document.getElementById('outputContainer');
            const variationsHeader = document.getElementById('variationsHeaderContainer');

            outputContainer.innerHTML = '';

            if (inputText.trim() === '') {
                outputContainer.innerHTML = '<p class="text-gray-500 text-center">Bitte geben Sie Text ein, um Fancy Fonts zu generieren.</p>';
                showMessage('Bitte geben Sie Text ein.', 'error');
                variationsHeader.classList.add('hidden');
                return;
            }

            let fontsToDisplay;
            if (isVariationMode && originalFontDetails) {
                fontsToDisplay = generateCharSubstitutionVariations(inputText, 5);
                variationsHeader.classList.remove('hidden');
            } else {
                fontsToDisplay = FONT_MAPS;
                variationsHeader.classList.add('hidden');
            }

            fontsToDisplay.forEach(font => {
                const textToDisplay = font.convertedText !== undefined ? font.convertedText : convertText(inputText, font);
                const fontType = font.type;
                const originalMapForVarying = font.map;

                const fontDiv = document.createElement('div');
                fontDiv.className = 'bg-gray-50 p-4 rounded-lg shadow-sm border border-gray-200 flex flex-col sm:flex-row items-center justify-between gap-3';

                const fontText = document.createElement('p');
                fontText.className = 'text-gray-900 text-lg sm:text-xl md:text-2xl break-words flex-grow'; // Schriftgröße angepasst
                fontText.textContent = textToDisplay;
                fontText.style.wordBreak = 'break-all';

                const varyBtn = document.createElement('button');
                varyBtn.className = 'vary-button px-4 py-2 bg-white text-gray-700 text-sm font-medium rounded-md hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 flex-shrink-0'; // Button-Stil angepasst
                varyBtn.textContent = 'Variieren';
                varyBtn.onclick = () => {
                    displayFancyFonts(inputText, true, { type: fontType, map: originalMapForVarying, convertedText: textToDisplay });
                    outputContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
                };

                fontDiv.appendChild(fontText);
                fontDiv.appendChild(varyBtn);
                outputContainer.appendChild(fontDiv);
            });

            if (!isVariationMode) {
                outputContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
            }
        }

        // Event-Listener für den Generieren-Button
        document.getElementById('generateButton').addEventListener('click', () => {
            const inputText = document.getElementById('inputText').value;
            displayFancyFonts(inputText, false, null);
        });

        // Initialisierung mit einer Nachricht
        window.onload = () => {
            document.getElementById('outputContainer').innerHTML = '<p class="text-gray-500 text-center">Geben Sie etwas ein und klicken Sie auf \'Generieren\', um die Magie zu sehen!</p>';
        };
    </script>
</body>
</html>