Search code examples
htmlcssfreemarkerkeycloak

Is there a way to add styles to my custom Keycloak Email theme?


Title says it all.

I have tried multiple things, but nothing seems to work.

I tried importing a stylesheet in my theme.properties. styles=css/styles.css

I tried doing my style directly in my html tags. <h1 style="color:blue;">

I tried having my style in my ftl file like so:

<html>
<style type="text/css">
body {
    margin: 0;
    font-family: 'Source Sans Pro';
    font-weight: 400;
    font-size: 16px;
}
.header{
    background-color: #B70E0C;
    width: 100%;
    height: 96px;
}

.footer{
    flex-shrink: 0;
    width: 100%;
    padding: 20px 0;
    text-align: center;
    font-size: 16px;
    background-color: #2D2D2D;
    z-index: 1;
    position: absolute;
    bottom: 0;
}

.footer a {
    color: white !important;
}

a:visited {
    color: initial;
}

.activate-btn{
    border-radius: 8px;
    padding: 12px 28px;
    background-color: #FDC300;
    color: black;
    border-style: hidden;
}
</style>
<body>
${kcSanitize(msg("emailVerificationBodyHtml", link, linkExpiration, realmName, 
linkExpirationFormatter(linkExpiration)))?no_esc}
</body>
</html>

Solution

  • Composing html email is not a simple thing like composing html web page, since almost all email services process incoming email in different ways. Some may ignore <style ..> refs, some may ignore several css properties. To make a crossplatform email (which will be rendered same in Gmail, Outlook, Thunderbird etc..) you will have to rollback to 2000's technologies like page layout based on tables, inlined css styles like <p style=".."> so you'd better look to email frameworks like Zurb.

    With zurb you can create and debug your email templates in browser like any other UI application from npm world. Then you can slice Zurb output to keycloak freemarker templates. At the end you'll got main freemarker template (with common headers, bottom links etc..), and bunch of freemarker macroses for paragraphs, links... This сomponents will encapsulate all ugliness like inlined css, tables etc, so your business templates will be simple and look pretty nice. This is what i got for execute required actions email

    <#import "template.ftl" as layout>
    <@layout.emailLayout title=msg('executeActionsSubject')?no_esc; section>
    
        <#if section = "header">
            <@layout.header text=msg("executeActionsSubject")?no_esc icon="status-icon-green%403x.png"/>
    
        <#elseif section = "content">
    
            <#outputformat "plainText">
                <#assign requiredActionsText>
                    <#if requiredActions??>
                        <ul>
                        <#list requiredActions>
                            <#items as reqActionItem><li>${msg("requiredAction.${reqActionItem}")}</li></#items>
                        </#list>
                        </ul>
                    </#if>
                </#assign>
            </#outputformat>
    
            <@layout.paragraph>
                ${msg("executeActionsBodyIntro", realmName)?no_esc}
            </@layout.paragraph>
    
            <b>
                ${msg("executeActionsList", requiredActionsText)?no_esc}
            </b>
    
            <@layout.paragraph>
                ${msg("executeActionsClickLinkNote")?no_esc}
            </@layout.paragraph>
    
            <@layout.mainAction text=msg("executeActionsButtonText")?no_esc href=link/>
    
            <@layout.secondaryText>
                ${kcSanitize(msg("expirationNote", linkExpirationFormatter(linkExpiration)))?no_esc}
            </@layout.secondaryText>
    
            <@layout.secondaryText>
                ${msg("mistakeDeleteText")?no_esc}
            </@layout.secondaryText>
    
        </#if>
    
    </@layout.emailLayout>
    

    UPD. There is also other frameworks for emails composing. For example MJML. Anyway development flow is completely the same for any of this frameworks, so feel free to use any of them.