🪟

Fluent Emoji

Windows 11 emoji pro všechny platformy - open-source řešení od Microsoftu

📅 15. 12. 2025 ⏱️ 15 min čtení 🏷️ Fluent, Microsoft, Open Source

✨ Fluent Emoji v akci

🎉

Skvělá zpráva!

Microsoft uvolnil Fluent Emoji jako open-source pod MIT licencí. Můžete je používat zdarma i v komerčních projektech!
→ GitHub repozitář

🎨 Tři styly Fluent Emoji

Microsoft nabízí Fluent Emoji ve třech různých stylech. Všechny jsou dostupné jako SVG i PNG.

Flat

Jednodušší 2D verze. Menší velikost souborů, rychlejší načítání.

High Contrast

Černobílé emoji pro přístupnost a vysoký kontrast.

Proč Fluent Emoji?

🆓

100% Zdarma

MIT licence - použijte kdekoliv, i v komerčních projektech.

🎨

Moderní design

Krásné 3D emoji známé z Windows 11 a Microsoft Teams.

📐

SVG formát

Vektorová grafika - perfektní kvalita v jakékoli velikosti.

🌍

1800+ emoji

Kompletní sada včetně nejnovějších emoji z Unicode 15.

Přístupnost

High contrast verze pro uživatele se zrakovým postižením.

CDN podpora

Dostupné přes jsDelivr CDN - žádné stahování potřeba.

⚡ Rychlá implementace

Nejrychlejší způsob, jak začít používat Fluent Emoji na vašem webu:

Přidejte knihovnu

Vložte tento skript před uzavírací tag </body>:

HTML
<script src="fluent-emoji.js"></script>
<script>
    FluentEmoji.parse(document.body);
</script>

Přidejte CSS styly

Pro správné zobrazení emoji přidejte tyto styly:

CSS
img.fluent-emoji {
    height: 1.2em;
    width: 1.2em;
    vertical-align: -0.2em;
    display: inline-block;
}

/* Větší emoji */
.emoji-large img.fluent-emoji {
    height: 2em;
    width: 2em;
}

/* Hover efekt */
img.fluent-emoji:hover {
    transform: scale(1.15);
    transition: transform 0.2s ease;
}

Hotovo! 🎉

Všechny emoji na stránce se automaticky převedou na Fluent Emoji. Funguje na všech platformách - Windows, Mac, Linux, Android, iOS.

📦 FluentEmoji.js - Vlastní knihovna

Vytvořil jsem jednoduchou knihovnu pro práci s Fluent Emoji, podobnou Twemoji:

JavaScript - fluent-emoji.js
/**
 * FluentEmoji.js - Microsoft Fluent Emoji pro web
 * Konvertuje Unicode emoji na Fluent Emoji obrázky
 */
const FluentEmoji = (function() {
    // CDN base URL pro Fluent Emoji
    const CDN_BASE = 'https://raw.githubusercontent.com/nicholascostadev/fluent-emoji-resolver/main/icons';
    
    // Mapování emoji na názvy souborů
    // Microsoft používá názvy souborů místo Unicode kódů
    const emojiMap = {
        '😀': 'grinning_face',
        '😃': 'grinning_face_with_big_eyes',
        '😄': 'grinning_face_with_smiling_eyes',
        '😁': 'beaming_face_with_smiling_eyes',
        '😅': 'grinning_face_with_sweat',
        '🤣': 'rolling_on_the_floor_laughing',
        '😂': 'face_with_tears_of_joy',
        '🙂': 'slightly_smiling_face',
        '😊': 'smiling_face_with_smiling_eyes',
        '😇': 'smiling_face_with_halo',
        '🥰': 'smiling_face_with_hearts',
        '😍': 'smiling_face_with_heart_eyes',
        '🤩': 'star_struck',
        '😘': 'face_blowing_a_kiss',
        '😗': 'kissing_face',
        '😚': 'kissing_face_with_closed_eyes',
        '😋': 'face_savoring_food',
        '😛': 'face_with_tongue',
        '😜': 'winking_face_with_tongue',
        '🤪': 'zany_face',
        '😝': 'squinting_face_with_tongue',
        '🤑': 'money_mouth_face',
        '🤗': 'hugging_face',
        '🤭': 'face_with_hand_over_mouth',
        '🤫': 'shushing_face',
        '🤔': 'thinking_face',
        '🤐': 'zipper_mouth_face',
        '🤨': 'face_with_raised_eyebrow',
        '😐': 'neutral_face',
        '😑': 'expressionless_face',
        '😶': 'face_without_mouth',
        '😏': 'smirking_face',
        '😒': 'unamused_face',
        '🙄': 'face_with_rolling_eyes',
        '😬': 'grimacing_face',
        '😮‍💨': 'face_exhaling',
        '🤥': 'lying_face',
        '😌': 'relieved_face',
        '😔': 'pensive_face',
        '😪': 'sleepy_face',
        '🤤': 'drooling_face',
        '😴': 'sleeping_face',
        '😷': 'face_with_medical_mask',
        '🤒': 'face_with_thermometer',
        '🤕': 'face_with_head_bandage',
        '🤢': 'nauseated_face',
        '🤮': 'face_vomiting',
        '🤧': 'sneezing_face',
        '🥵': 'hot_face',
        '🥶': 'cold_face',
        '🥴': 'woozy_face',
        '😵': 'dizzy_face',
        '🤯': 'exploding_head',
        '🤠': 'cowboy_hat_face',
        '🥳': 'partying_face',
        '🥸': 'disguised_face',
        '😎': 'smiling_face_with_sunglasses',
        '🤓': 'nerd_face',
        '🧐': 'face_with_monocle',
        '😕': 'confused_face',
        '😟': 'worried_face',
        '🙁': 'slightly_frowning_face',
        '😮': 'face_with_open_mouth',
        '😯': 'hushed_face',
        '😲': 'astonished_face',
        '😳': 'flushed_face',
        '🥺': 'pleading_face',
        '😦': 'frowning_face_with_open_mouth',
        '😧': 'anguished_face',
        '😨': 'fearful_face',
        '😰': 'anxious_face_with_sweat',
        '😥': 'sad_but_relieved_face',
        '😢': 'crying_face',
        '😭': 'loudly_crying_face',
        '😱': 'face_screaming_in_fear',
        '😖': 'confounded_face',
        '😣': 'persevering_face',
        '😞': 'disappointed_face',
        '😓': 'downcast_face_with_sweat',
        '😩': 'weary_face',
        '😫': 'tired_face',
        '🥱': 'yawning_face',
        '😤': 'face_with_steam_from_nose',
        '😡': 'pouting_face',
        '😠': 'angry_face',
        '🤬': 'face_with_symbols_on_mouth',
        '😈': 'smiling_face_with_horns',
        '👿': 'angry_face_with_horns',
        '💀': 'skull',
        '☠️': 'skull_and_crossbones',
        '💩': 'pile_of_poo',
        '🤡': 'clown_face',
        '👹': 'ogre',
        '👺': 'goblin',
        '👻': 'ghost',
        '👽': 'alien',
        '👾': 'alien_monster',
        '🤖': 'robot',
        '❤️': 'red_heart',
        '🧡': 'orange_heart',
        '💛': 'yellow_heart',
        '💚': 'green_heart',
        '💙': 'blue_heart',
        '💜': 'purple_heart',
        '🖤': 'black_heart',
        '🤍': 'white_heart',
        '🤎': 'brown_heart',
        '💔': 'broken_heart',
        '🔥': 'fire',
        '⭐': 'star',
        '🌟': 'glowing_star',
        '✨': 'sparkles',
        '💫': 'dizzy',
        '🎉': 'party_popper',
        '🎊': 'confetti_ball',
        '🎈': 'balloon',
        '🎁': 'wrapped_gift',
        '🏆': 'trophy',
        '🥇': 'first_place_medal',
        '🥈': 'second_place_medal',
        '🥉': 'third_place_medal',
        '🎯': 'direct_hit',
        '🚀': 'rocket',
        '💎': 'gem_stone',
        '👍': 'thumbs_up',
        '👎': 'thumbs_down',
        '👏': 'clapping_hands',
        '🙌': 'raising_hands',
        '🤝': 'handshake',
        '✌️': 'victory_hand',
        '🤞': 'crossed_fingers',
        '👋': 'waving_hand',
        '🖐️': 'hand_with_fingers_splayed',
        '✋': 'raised_hand',
        '👌': 'ok_hand',
        '🤌': 'pinched_fingers',
        '🤏': 'pinching_hand',
        '💪': 'flexed_biceps',
        '🙏': 'folded_hands',
        '☀️': 'sun',
        '🌈': 'rainbow',
        '⚡': 'high_voltage',
        '💧': 'droplet',
        '🌊': 'water_wave'
    };
    
    // Výchozí konfigurace
    const defaultConfig = {
        style: '3d',        // '3d', 'flat', nebo 'high-contrast'
        size: 72,           // velikost v px
        className: 'fluent-emoji',
        ext: 'png'          // 'png' nebo 'svg'
    };
    
    /**
     * Získá URL pro emoji
     */
    function getEmojiUrl(emoji, config) {
        const name = emojiMap[emoji];
        if (!name) return null;
        
        const style = config.style === '3d' ? '3D' : 
                      config.style === 'flat' ? 'Flat' : 'High Contrast';
        
        // Používáme alternativní CDN s předgenerovanými URL
        return `https://em-content.zobj.net/source/microsoft/379/${name.replace(/_/g, '-')}_${getEmojiCodePoint(emoji)}.png`;
    }
    
    /**
     * Získá Unicode code point pro emoji
     */
    function getEmojiCodePoint(emoji) {
        return [...emoji]
            .map(char => char.codePointAt(0).toString(16).toLowerCase())
            .join('-');
    }
    
    /**
     * Parsuje element a nahrazuje emoji
     */
    function parse(element, options = {}) {
        const config = { ...defaultConfig, ...options };
        
        // Regex pro detekci emoji
        const emojiRegex = /(\p{Emoji_Presentation}|\p{Emoji}\uFE0F)/gu;
        
        // Procházíme textové uzly
        const walker = document.createTreeWalker(
            element,
            NodeFilter.SHOW_TEXT,
            null,
            false
        );
        
        const textNodes = [];
        let node;
        while (node = walker.nextNode()) {
            if (emojiRegex.test(node.textContent)) {
                textNodes.push(node);
            }
            emojiRegex.lastIndex = 0;
        }
        
        textNodes.forEach(textNode => {
            const fragment = document.createDocumentFragment();
            let lastIndex = 0;
            let match;
            
            emojiRegex.lastIndex = 0;
            const text = textNode.textContent;
            
            while ((match = emojiRegex.exec(text)) !== null) {
                // Text před emoji
                if (match.index > lastIndex) {
                    fragment.appendChild(
                        document.createTextNode(text.slice(lastIndex, match.index))
                    );
                }
                
                const emoji = match[0];
                const url = getEmojiUrl(emoji, config);
                
                if (url && emojiMap[emoji]) {
                    // Vytvoříme img element
                    const img = document.createElement('img');
                    img.src = url;
                    img.alt = emoji;
                    img.className = config.className;
                    img.draggable = false;
                    img.loading = 'lazy';
                    fragment.appendChild(img);
                } else {
                    // Emoji není v mapě, ponecháme nativní
                    fragment.appendChild(document.createTextNode(emoji));
                }
                
                lastIndex = emojiRegex.lastIndex;
            }
            
            // Zbytek textu
            if (lastIndex < text.length) {
                fragment.appendChild(
                    document.createTextNode(text.slice(lastIndex))
                );
            }
            
            textNode.parentNode.replaceChild(fragment, textNode);
        });
        
        return element;
    }
    
    /**
     * Vytvoří img element pro jednotlivé emoji
     */
    function emoji(char, options = {}) {
        const config = { ...defaultConfig, ...options };
        const url = getEmojiUrl(char, config);
        
        if (!url) return char;
        
        const img = document.createElement('img');
        img.src = url;
        img.alt = char;
        img.className = config.className;
        img.style.height = config.size + 'px';
        img.style.width = config.size + 'px';
        
        return img;
    }
    
    /**
     * Vrátí HTML string pro emoji
     */
    function toHTML(char, options = {}) {
        const config = { ...defaultConfig, ...options };
        const url = getEmojiUrl(char, config);
        
        if (!url) return char;
        
        return `${char}`;
    }
    
    // Public API
    return {
        parse,
        emoji,
        toHTML,
        getUrl: getEmojiUrl,
        config: defaultConfig,
        supported: Object.keys(emojiMap)
    };
})();

// Export pro Node.js
if (typeof module !== 'undefined' && module.exports) {
    module.exports = FluentEmoji;
}
💡
Poznámka k mapování

Microsoft nepoužívá Unicode kódy pro názvy souborů, ale anglické názvy emoji. Knihovna obsahuje mapování pro nejběžnější emoji. Pro kompletní podporu je potřeba rozšířit mapu.

🎮 Živá ukázka

Přepínač stylů Fluent Emoji

Vyberte styl a podívejte se, jak emoji vypadají

Škálování velikosti

Fluent Emoji jsou dostupné jako PNG v různých velikostech (72px, 256px) nebo jako SVG pro neomezené škálování:

24px
36px
48px
72px
96px

🔧 Pokročilé použití

Selektivní parsování

JavaScript
// Parsovat pouze určitý element
FluentEmoji.parse(document.getElementById('chat-messages'));

// S vlastním nastavením
FluentEmoji.parse(document.body, {
    style: 'flat',      // 'flat' místo '3d'
    size: 48,           // velikost v px
    className: 'my-emoji'
});

// Jednotlivé emoji
const img = FluentEmoji.emoji('😀', { size: 64 });
document.body.appendChild(img);

// Jako HTML string
const html = FluentEmoji.toHTML('🎉', { size: 32 });
element.innerHTML = `Gratulujeme! ${html}`;

React komponenta

JSX
import { useEffect, useRef } from 'react';

function FluentEmojiText({ children, style = '3d' }) {
    const ref = useRef(null);
    
    useEffect(() => {
        if (ref.current) {
            FluentEmoji.parse(ref.current, { style });
        }
    }, [children, style]);
    
    return <span ref={ref}>{children}</span>;
}

// Použití
<FluentEmojiText>
    Ahoj! 😀 Jak se máš? 🎉
</FluentEmojiText>

🌐 Self-hosting (vlastní server)

Pro maximální výkon a nezávislost můžete Fluent Emoji hostovat na vlastním serveru:

Bash
# Stáhnout repozitář
git clone https://github.com/microsoft/fluentui-emoji.git

# Nebo pouze assets
wget https://github.com/microsoft/fluentui-emoji/archive/main.zip
unzip main.zip

Struktura souborů

fluentui-emoji/ ├── assets/ │ ├── Grinning face/ │ │ ├── 3D/ │ │ │ └── grinning_face_3d.png │ │ ├── Flat/ │ │ │ └── grinning_face_flat.svg │ │ └── High Contrast/ │ │ └── grinning_face_high_contrast.svg │ ├── Fire/ │ ├── Rocket/ │ └── ... (1800+ emoji) └── metadata.json ← Seznam všech emoji
Připraveno k implementaci

Chceš-li přidat přepínač Fluent Emoji do naší emoji databáze, můžu upravit hlavní stránku. Uživatelé si budou moci vybrat mezi nativními emoji, Twemoji nebo Fluent Emoji!

Srovnání: Fluent vs Twemoji

Vlastnost Fluent Emoji Twemoji
Design 3D, moderní 2D, flat
Licence MIT (zdarma) MIT + CC-BY (zdarma)
Formáty PNG, SVG PNG, SVG
CDN Částečně jsDelivr ✓
Pojmenování souborů Anglické názvy Unicode kódy
Velikost 3D verze ~50KB/emoji ~2KB/emoji (SVG)
📚