Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

email template styling #268

Open
woodz- opened this issue Feb 1, 2019 · 5 comments
Open

email template styling #268

woodz- opened this issue Feb 1, 2019 · 5 comments

Comments

@woodz-
Copy link

woodz- commented Feb 1, 2019

I may have a kind of confused understanding, when it comes to putting styles into email templates.
First I'd like to depict my rather ideal imagination.

From the message.html template I would derive a user defined one, putting / overriding head and body sections in there. While overriding the head section I'd introduce an external style sheet then taking over the super content. In the step of processing for sending an email, the premailer would transform the external style sheet into inline styles and finally the message is delivered to desired recipients, which are configured unter the Subscriptions admin section.

To be able to inherit from message.html, a modification of this template would be required, like this:

{% load thumbnail i18n %}<!DOCTYPE html>

<html>
<head>
  {% block head %}
    <meta charset="utf-8">
    <title>{{ newsletter.title }}: {{ message.title }}</title>
  {% endblock head %}
</head>
<body>
  {% block body %}
    <h1>{{ newsletter.title }}</h1>
    <h2>{{ message.title }}</h2>
    {% for article in message.articles.all %}
        <h3>{{ article.title }}</h3>
        
        {% thumbnail article.image "200x200" as image %}
          <img src="http://{{ site.domain }}{{ image.url }}" width="{{ image.width }}" height="{{ image.height }}">
        {% endthumbnail %}

        <div>{{ article.text|safe }}</div>
        
        {% if article.url %}
            <div><a href="{{ article.url }}">{% trans "Read more" %}</a></div>
        {% endif %}
    {% endfor %}
    
    <ul>
        {% if submission.publish %}
        <li><a href="http://{{ site.domain }}{{ submission.get_absolute_url }}">{% trans "Read message online" %}</a></li>
        {% endif %}
        <li><a href="http://{{ site.domain }}{% url "newsletter_unsubscribe_request" newsletter.slug %}">{% trans "Unsubscribe" %}</a></li>
    </ul>
  {% endblock body %}
</body>
</html>

Then the derived template could look like this:

{% extends "newsletter/message/message.html" %}

{% load static %}
<!-- premailer is not an option in templates, only for plain html, due to use of lxml -->

{% block head %}
  <link rel="stylesheet" href="message.css"> 
  {{ block.super }}
{% endblock head %}

Following the doc of django-premailer, the derivation would look like:

{% extends "newsletter/message/message.html" %}

{% load static premailer %}{% premailer "localhost:8080" %}
<!-- premailer is not an option in templates, only for plain html, due to use of lxml -->

{% block head %}
  <link rel="stylesheet" href="message.css"> 
  {{ block.super }}
{% endblock head %}
{% endpremailer %}

At this point it comes to a dead end. Following the doc of premailer, we encounter a statement:

premailer does this. It parses an HTML page, looks up style blocks and parses the CSS. It then uses the lxml.html parser to modify the DOM tree of the page accordingly.

Since premailer only processes plain standard conform html, it fails to work on django templates due to lxml.
So my question is: what is a generic way of introducing styles in newsletter's templates, email templates especially?
@Sheepzez did this in the past by an any how configuration. Maybe it would be possible to shed some light on this? Here is the thread: #178, where I was also asking for details.

Thanks for taking time.

@mrxsal
Copy link

mrxsal commented Apr 7, 2021

Hi @woodz- ,
Did you find an answer to your question? I'm currently trying to figure this out as well.

@woodz-
Copy link
Author

woodz- commented Apr 7, 2021

Hello @mrxsal,
unfortunately not. The main issue is, that django calls its templates *.html, while in truth this is an awful decision since the template syntax simply isn't html, it's a fake.

@thenewguy
Copy link

You can call your templates anything you like. Django doesn't require the html extension.

A simple solution if you want to handle it all inside the template - try django compressor. You can output css inline. You could then run it through an email css optimizer

@thenewguy
Copy link

Also (untested) you would probably write your snippet like this instead if you wanted to apply premailer that way:

{% extends "newsletter/message/message.html" %}

{% load static premailer %}
<!-- premailer is not an option in templates, only for plain html, due to use of lxml -->

{% block head %}
  {% premailer "localhost:8080" %}
    <link rel="stylesheet" href="message.css"> 
    {{ block.super }}
  {% endpremailer %}
{% endblock head %}

@mrxsal
Copy link

mrxsal commented Apr 9, 2021

I am a little bit of a django noobie but I thought at least I can explain how I got it working in the end.

First of all, I am using bootstrap 5 for front-end styling. Initially I tried to style my emails just like how I would style my web pages, and I hoped that using django-premailer would enable me to do so.
In the end I found the django-inlinecss package to work decently together with django-newsletter. Only downside is that you can only use one css file, and the complete bootstrap.css file is too big for it to handle. So, I copied the smaller bootstrap grid source files into a new (email.css) css file and added any other required styling. I changed the message.html file to something like this:

{% load thumbnail i18n %}
<!DOCTYPE html>
{% load static %}
{% load inlinecss %}

{% inlinecss "css/email.css" %}
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>{{ newsletter.title }}: {{ message.title }}</title>
</head>
<div class="container">
    <div class="row justify-content-center">
        <div class="col-10 text-center">
            <a href="xxx"><img src="{% static xxx' %}" alt="" width="200" height="50" class="mb-3"></a>
        </div>
    </div>
</div>
</body>
</html>
{% endinlinecss %}

As you can see, i'm utilizing the bootstrap styling, and it works like a charm. (tested on gmail)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants