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

Gmail and display:inline-block #80

Open
hteumeuleu opened this issue May 27, 2020 · 6 comments
Open

Gmail and display:inline-block #80

hteumeuleu opened this issue May 27, 2020 · 6 comments
Labels
Gmail Webmail, iOS and Android apps

Comments

@hteumeuleu
Copy link
Owner

Since a week or so, I'm starting to see issues in Gmail when using display:inline-block to set columns side by side. It's as if the space between two elements would be forced there (even though I use font-size:0 on a parent element to remove it.

A solution I found is to use HTML comments between the two elements to eliminate the white space.

Here's what it looks like in my iPhone SE (first gen):

Example email showing two columns failing behind each others

Here's the code with two examples, the first one breaking and the second one (with the comments fix) :

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Gmail display:inline-block bug</title>
</head>
<body>
	<div style="font-size:0; text-align:center;">
		<div style="display:inline-block; width:50%; font-size:16px; background:orange; height:120px;">
			A
		</div>
		<div style="display:inline-block; width:50%; font-size:16px; background:orange; height:120px;">
			B
		</div>
	</div>
	<div style="font-size:0; text-align:center;">
		<div style="display:inline-block; width:50%; font-size:16px; background:green; height:120px;">
			A
		</div><!--
		--><div style="display:inline-block; width:50%; font-size:16px; background:green; height:120px;">
			B
		</div>
	</div>
</body>
</html>

But I've found this to be very inconsistent. It doesn't happen on all my devices. And it doesn't happen on all accounts in Gmail. Can anyone else test the above code and share what your results are?

@hteumeuleu hteumeuleu added the Gmail Webmail, iOS and Android apps label May 27, 2020
@M-J-Robbins
Copy link
Contributor

Just had a quick look into this. Gmail on iOS adds word-spacing: 1px; to the body. If you add word-spacing:normal it should fix it.

This is what Gmail adds

body {
  -webkit-text-size-adjust: none;
  background-color: #ffffff;
  color: #313131;
  font-family: Roboto;
  font-size: 16px;
  line-height: 1.4;
  margin: 0;
  margin-right: 15px;
  padding: 0;
  word-spacing: 1px;
  word-wrap: break-word;
  min-height: 10px;
}

@hteumeuleu
Copy link
Owner Author

Wow, nice! This works perfectly. (By adding <body style="word-spacing:normal"> to my previous example.) Out of curiousity, how did you get those default styles on the body? Using a proxy?

@M-J-Robbins
Copy link
Contributor

I got it from the Litmus processed HTML view.

Here's the full processed HTMl from your code above.

<head>
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <script type="text/javascript" src="termhighlighter.bin"></script>
    <script>gbt = {};gbt.documentContainerDivId = 'gbt_container';gbt.doubleTapToZoom = false;</script>
    <style type="text/css">
        body {
  -webkit-text-size-adjust: none;
  background-color: #ffffff;
  color: #313131;
  font-family: Roboto;
  font-size: 16px;
  line-height: 1.4;
  margin: 0;
  margin-right: 15px;
  padding: 0;
  word-spacing: 1px;
  word-wrap: break-word;
  min-height: 10px;
}

.term-highlighted {
  background-color: rgba(251, 246, 167, 0.5);
}

.gbtc {
  color:#757575 !important;
}

pre {
  white-space: pre-wrap;
}

    </style>
    <style type="text/css">
        
    </style>
</head>
<body class="(null)">
    <div id="gbt_container" style="float: left; transform-origin: 0px 0px; transform: translate3d(0px, 0px, 0px) scale3d(1, 1, 1);"><div style="margin: 0px 16px;" class=""><u></u>


	
	

<div>
	<div style="font-size:0;text-align:center">
		<div style="display:inline-block;width:50%;font-size:16px;background:orange;height:120px">
			A
		</div>
		<div style="display:inline-block;width:50%;font-size:16px;background:orange;height:120px">
			B
		</div>
	</div>
	<div style="font-size:0;text-align:center">
		<div style="display:inline-block;width:50%;font-size:16px;background:green;height:120px">
			A
		</div><div style="display:inline-block;width:50%;font-size:16px;background:green;height:120px">
			B
		</div>
	</div>
</div>

</div></div>

<script type="text/javascript">
    /** @type {Object} */
var gbt;

/** @type {number} The x transform offset used when gbt.update is called. */
var gbtX;
/** @type {number} The y transform offset used when gbt.update is called. */
var gbtY;
/** @type {number} The scale transform used when gbt.update is called. */
var gbtScale;

/** @type {number} Millis since last touchend event for double tap to zoom. */
gbt.lastTouchEnd = 0;
/** @type {number} Maximum ms between taps for a double tap. */
gbt.doubleTapCutoff = 500;
/** @type {number} Current number of touches in progress. */
gbt.touchCount = 0;
/** @type {string} The name of the container div. */
gbt.documentContainerDivId;
/** @type {boolean} If double-tap to zoom should be enabled. */
gbt.doubleTapToZoom;

/**
 * Updates the css transform to reflect the current gbt(X|Y|Scale) state.
 * @param {boolean} animated Whether the update should animate from the current
 *     state.
 */
gbt.update = function (animated) {
    gbt.lastTouchEnd = 0;
    var body = document.getElementById(gbt.documentContainerDivId);
    if (!body) {
        return;
    }
    var x = gbtX;
    var y = gbtY;
    var scale = gbtScale;
    var update = function () {
        body.style.webkitTransformOrigin = '0 0';
        body.style.webkitTransform = 'translate3d(-' + x + 'px,-' + y +
            'px,0px) scale3d(' + scale + ',' + scale + ',1)';
    };
    if (animated) {
        var duration = 200;
        body.style.webkitTransition =
            '-webkit-transform ' + duration + 'ms ease-in';
        window.setTimeout(function () {
            update();
            window.setTimeout(function () {
                body.style.webkitTransition = 'none';
            }, duration);
        }, 0);
    } else {
        update();
    }
    return;
};

/**
 * Serializes a rectangle to CGRectFromNSString-format.
 * @param {!ClientRect} rect .
 * @return {string} The serialized string.
 */
gbt.serializeRect = function (rect) {
    return '{{' + rect.left + ', ' + rect.top + '}, {' + rect.width + ', ' +
        rect.height + '}}';
};

/**
 * Returns, as a string, the bounding rectangle of the focused element, or the
 * empty string if there is no focused element.
 * @return {string} The bounding rectangle.
 */
gbt.focusRect = function () {
    if (document.body && document.activeElement != document.body) {
        var rect = document.activeElement.getBoundingClientRect();
        if (rect) {
            return gbt.serializeRect(rect);
        }
    }
    return '';
};

/**
 * Sends a message to the app.
 * @param {string} data The message to send.
 */
gbt.rpc = function (data) {
    var iframe = document.createElement('iframe');
    iframe.setAttribute('src', 'gbt://#' + data);
    document.documentElement.appendChild(iframe);
    iframe.parentNode.removeChild(iframe);
    iframe = null;
};

/**
 * Sends a messages to the app with the given command and the bounding rect for
 * the given DOM element.
 * @param {string} command The command ID to send.
 * @param {Object} target The target DOM element.
 */
gbt.rpcWithRectForTarget = function (command, target) {
    var rect = target.getBoundingClientRect();
    gbt.rpc('rpc=' + command + '&left=' + rect.left + '&width=' + rect.width +
            '&top=' + rect.top + '&height=' + rect.height);
};

if (gbt.doubleTapToZoom) {
    document.body.addEventListener('touchstart', function (e) {
        gbt.touchCount += e.changedTouches.length;
    });
    document.body.addEventListener('touchcancel', function (e) {
        e.preventDefault();
        gbt.touchCount -= e.changedTouches.length;
    });
    document.body.addEventListener('touchend', function (e) {
        e.preventDefault();
        gbt.touchCount -= e.changedTouches.length;
        if (gbt.touchCount > 0) {
            return;
        }
        var now = new Date().getTime();
        if (now - gbt.lastTouchEnd < gbt.doubleTapCutoff) {
            // Zoom
            gbt.rpcWithRectForTarget('zoom', e.target);
            gbt.lastTouchEnd = 0;
        } else {
            gbt.lastTouchEnd = now;
        }
    }, false);
}

document.body.addEventListener('focusin', function (e) {
    gbt.rpcWithRectForTarget('focusin', e.target);
});

if (typeof gbtX !== undefined && typeof gbtY !== undefined &&
    typeof gbtScale !== undefined) {
    gbt.update(false);
}

</script>
</body>

@hteumeuleu
Copy link
Owner Author

Ha, nice! I didn't know this worked for mobile apps as well.

@pbiolsi
Copy link

pbiolsi commented May 28, 2020 via email

FelixSchwarz added a commit to FelixSchwarz/mjml-python that referenced this issue Apr 1, 2021
… commit 9ee7dc274)

upstream commit found in 4.8.0

commit 9ee7dc2746b3dc4f1ea1a979cdd9c6807392ec34
Author: Jack Steele <[email protected]>
Date:   Thu Oct 1 14:45:02 2020 +0100

    Adjust skeleton to add word-spacing: normal to body of html

The motivation to do this is mentioned in upstream pull request 2049:

  Fix issue with stacking columns within mj-group in Gmail for IOS
  mjmlio/mjml#2049

> This PR resolves the bug in Gmail on IOS where the word-spacing: 1px is
> added to the body causing the mj-group columns to stack. The issue is
> outlined here hteumeuleu/email-bugs#80 and the suggested fix is provided
> by Mark Robbins.
> ...
> Columns are stacking in IOS 14 on Gmail. The fix will ensure that the
> columns remain inline.
@JayOram
Copy link

JayOram commented Jul 16, 2024

@pbiolsi - I know this is quite old - but this repo has all the needed CSS resets/normalise attributes for email: https://github.com/JayOram/email-css-resets

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Gmail Webmail, iOS and Android apps
Projects
None yet
Development

No branches or pull requests

4 participants