Tips for creating responsive emails

Yesterday, I posted about my email newsletter and received some helpful feedback on creating a good structure. I implemented the suggestions provided into my newsletter and also added media query code to make layout adjustments for supported email clients. However, I encountered an issue as the media queries did not work as expected in my email newsletter. If you would like to see the visual representation of the desktop version email, and the mobile version email. The main difference between the two versions is visible in the four columns section.

  1. In the mobile version, there should be two columns instead of four.
  2. The last two columns need to be positioned below the first two columns with spacing from the top to ensure that the vertical borders do not touch.
  3. For desktop view, every column should have a right border except for the last one. In the mobile view, the second and fourth columns should not have a right border.

To achieve these layout changes, I structured my code in the following way:

  1. There are four columns below the logo, organized as two separate tables with two columns each. The parent table's width is set at 640 pixels, while the child tables' width is set at 320 pixels. The first child table aligns to the left so they are displayed side by side. To ensure proper display in mobile view, I adjusted the main table's width to 320 pixels so the child tables stack vertically.
  2. I added padding-top: 20px to the second child table in the mobile view to create space between it and the table above.
  3. For columns without a right-border property in the mobile view, I applied a specific class and set border: 0; for those columns.

In the head code:

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, maximum-scale=1.0, minimum-scale=1.0, initial-scale=1.0" />
<title>Email</title>
<style>
@media only screen and (max-device-width: 480px) { 
    table[class="mainTable"] {
        width: 320px !important;
    }
    table[class="subTable"] {
        padding: 20px 0 0 !important;   
    }
    td[class="noBorder"] {
        border: 0 !important;
    }
}
</style>

In the body code:

<table width="640" border="0" cellspacing="0" cellpadding="0" class="mainTable" style="margin: 0px auto; font-family: Helvetica, Arial, sans-serif; padding: 35px 0 0;">
        <tr>
            <td style="font-size: 25px;">
                LOGO
            </td>
        </tr>
        <tr>
            <td>
                <table align="left" width="320" border="0" cellspacing="0" cellpadding="0" style="margin: 0; padding: 0;">
                    <tr>
                        <td align="center" valign="top" style="padding: 15px 0 15px; width: 160px; height: 150px; border-right: 1px solid #666;">
                            <p style="margin: 0; padding: 5px 0 10px;">Remaining</p>
                            <p style="font-size: 35px; margin: 0 0 20px;">12d, 17hr</p>
                            <a style="background: #ccc; color: #000; font-weight: bold; text-decoration: none; padding: 5px 10px;" href="#">Visit</a>
                        </td>
                        <td align="center" valign="top" class="noBorder" style="padding: 15px 0 15px; width: 160px; height: 150px; border-right: 1px solid #666;">
                            <p style="margin: 0; padding: 5px 0 10px;">Remaining</p>
                            <p style="font-size: 35px; margin: 0 0 20px;">12d, 17hr</p>
                            <a style="background: #ccc; color: #000; font-weight: bold; text-decoration: none; padding: 5px 10px;" href="#">Visit</a>
                        </td>
                    </tr>
                </table>
                <table width="320" border="0" cellspacing="0" cellpadding="0" class="subTable" style="margin: 0; padding: 0;">
                    <tr>
                        <td align="center" valign="top" style="padding: 15px 0 15px; width: 160px; height: 150px; border-right: 1px solid #666;">
                            <p style="margin: 0; padding: 5px 0 10px;">Remaining</p>
                            <p style="font-size: 35px; margin: 0 0 20px;">12d, 17hr</p>
                            <a style="background: #ccc; color: #000; font-weight: bold; text-decoration: none; padding: 5px 10px;" href="#">Visit</a>
                        </td>
                        <td align="center" valign="top" style="padding: 15px 0 15px; width: 160px; height: 150px;">
                            <p style="margin: 0; padding: 5px 0 10px;">Remaining</p>
                            <p style="font-size: 35px; margin: 0 0 20px;">12d, 17hr</p>
                            <a style="background: #ccc; color: #000; font-weight: bold; text-decoration: none; padding: 5px 10px;" href="#">Visit</a>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
        <tr>
            <td>
                <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
            </td>
        </tr>
        <tr>
            <td>
                <ul>
                    <li>Item 1</li>
                    <li>Item 2</li>
                    <li>Item 3</li>
                    <li>Item 4</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>
                <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
            </td>
        </tr>
    </table>

Despite these efforts, the changes did not reflect correctly in the mobile view. Upon testing in the Android Gmail app, which may not fully support media query, and the Sony android default Email app which should support it, no significant change was observed. This lack of responsiveness warrants further investigation and testing across different devices. Unfortunately, I currently do not have access to other mobile devices for testing purposes.

Answer №1

Creating a responsive email can feel like a futile task, given the number of email clients that may not display your design as intended.

When it comes to HTML emails, it's best to stick to the basics - tables, images, and inline styles like it's 1999.

If you really need it to be responsive, consider removing table widths and letting them adapt naturally.

For more tips on coding HTML emails, check out this resource:

Answer №2

Yesterday, I shared a response (the duplicate that was later deleted) where I believe I provided a link to this basic responsive example.

I noticed that you have not implemented the display:block; toggle. Your email section should be structured like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title></title>
  <style type="text/css">
    @media only screen and (max-width: 600px) { .switch { width:100%; display:block; } }
  </style>
</head>
<body>

<table width="600" border="0" cellpadding="0" cellspacing="0">
  <tr>
    <td width="50%" class="switch">
      <table width="100%" border="0" cellpadding="0" cellspacing="0">
        <tr>
          <td width="50%" valign="top" style="padding:30px;" bgcolor="#333333">
            Cell 1
          </td>
          <td width="50%" valign="top" style="padding:30px;" bgcolor="#444444">
            Cell 2
          </td>
        </tr>
      </table>
    </td>
    <td width="50%" class="switch">
      <table width="100%" border="0" cellpadding="0" cellspacing="0">
        <tr>
          <td width="50%" valign="top" style="padding:30px;" bgcolor="#555555">
            Cell 3
          </td>
          <td width="50%" valign="top" style="padding:30px;" bgcolor="#666666">
            Cell 4
          </td>
        </tr>
      </table>
    </td>
  </tr>
</table>

</body></html>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Distinguishing between client side rendering and server side rendering is the backbone of web development

My goal is to give users the option to request webpages from my website either directly from the server or by clicking on links, which will be managed by Backbone's router. When a user requests a webpage directly from the server, they will receive a ...

Wordpress easily adjusts post alignments for a seamless display

Can anyone help me figure out how to properly align posts in Wordpress to match the example image attached? I've tried using inline-block or float with CSS/HTML, but the posts are not aligning correctly. I'm unsure of what this method is called s ...

The CSS 'top' attribute is without impact

As I begin my journey with CSS, I am eager to grasp some of its behaviors. In the CSS file, the following code is defined: #spa { position : absolute; top : 8px; left : 8px; bottom : 8px; right : 8px; min-height : 500px; min-width : 500px ...

Issue with Dropdown Menu functionality while using multiple dropdown options

I am currently experimenting with dropdown menus from W3Schools and have encountered an issue when trying to implement two dropdown options. The code works fine for a single dropdown, but when I try to add a second one using GetElementsByClassName instead ...

What is the best way to display content next to an image, as well as below the image once it finishes?

Currently, I am working on customizing my blog posts in WordPress. My goal is to have the content of each post displayed next to the post thumbnail, and once the image ends, the content should seamlessly flow underneath it from the left side. I have imple ...

The background color spills outside the column when using 100% width

Bootstrap 5 is being used, and two columns have been created on the page. The current output looks like this: https://i.stack.imgur.com/P6oZs.png Now, there's a need to display an orange color from end to end of the left column. To achieve this, h- ...

Add a new division to a component when a specific event handler is triggered by another component using React and the reduce method

Currently, I am developing an interactive drag-and-drop application using React and Redux. My goal is to insert a new div element into a container when the ondragstart event handler is triggered by a component. The component responsible for the dragging o ...

"Trouble encountered while trying to display Angular in an HTML document

In my Angular project, there is a feature where a list of orders is displayed in one view. Each order is represented by its title only. When the user clicks on the title, they should be redirected to a new view showing the complete content of that particul ...

`Can you guide me on the proper path for designing this website layout?`

As I embark on creating my first website, I have a specific vision in mind. I want the full display on a computer screen to show all the information and links without any need for scrolling. However, when the window is resized to smaller screens, I would l ...

Tips for aligning the first row of a table with a line of text

I need assistance aligning the first row of a table with a line of text. Specifically, I am trying to achieve ** some text ** |first row of table      |             ...

`Cannot locate the CSS file on my local server`

My Node.js application uses the Express.js framework, and I am attempting to execute the following code: app.use('/public', express.static(path.join(__dirname,'public'))); However, I encountered the following error message: The CSS ...

Issue with Jquery .html() not adding content

Utilizing Jquery to dynamically update a list based on dropdown selections. After successfully fetching data and constructing the correct HTML content within the "item" variable, applying .html(item) does not result in the expected HTML updates. <div c ...

Unveiling the method to fetch the emitted value from a child component and incorporate it into the parent component's return data in Vue

How can I retrieve the title value passed by the Topbar component and incorporate it into the data() return section? I attempted to create a method to pass the value, but was unsuccessful despite being able to successfully log the value in the parent file. ...

Exploring HTML5 video playback in AngularJS

When I use this code: <video id="video" class="video-js vjs-default-skin" controls width="640" height="264"> <source src="http://localhost:3000/files/public/photos/Let-her-go.mp4" type='video/mp4' /> <p class="v ...

Implementing a delay between two div elements using jQuery

I have two Divs with the class "sliced", each containing three images with the class "tile". When I animate using jQuery, I am unable to add a delay between the "sliced" classes. However, I have successfully added a delay between the "tile" classes. index ...

Overcoming Troublesome Login Input Box in Web

In an effort to streamline tasks in our office, I am working on automating certain processes. Specifically, this program is designed to log into our insurance company's website and extract information for payroll purposes. Below is the code snippet th ...

What is the method for pulling information from MySQL and presenting it on a website using Node.js?

Currently, my goal is to retrieve data from MySQL and showcase it on my HTML page. The code snippet in server.js looks like this: const path = require('path'); const express = require('express'); const bodyParser = require("body-pa ...

Optimal Strategy: Utilizing Spring Boot for Backend Development and jQuery for Frontend Interface

I am currently tackling a project that involves a Spring Boot 2 Backend and a jQuery Frontend. The frontend communicates with the backend by sending Ajax requests to Spring REST controllers in order to interact with database entities. One of the challenge ...

Adjusting image size to accommodate responsive column cell using CSS

I've been working on optimizing my mobile website using a responsive column layout. The challenge I'm facing is getting the images within each column to stretch to 100% width while automatically adjusting their height. I experimented with settin ...

Using jQuery to swap out intricate background designs

I'm attempting to use jQuery to change the background-color of an element from: background: transparent linear-gradient(#C0B 45%, #C0B) to: background-color:#000; Unfortunately, my attempt to remove the background property with .removeAttr() has n ...