46

Google adds styles to the maps container that override my styles.
I know how to fix this. But the API (v3.8/9/exp) also loads the webfont "Roboto" which I don't really need/want.

Is there any setting/option/way around this?
Can I prevent the API from adding the extra CSS?

This is the code the google-maps-API adds to the <head> of my page:

<style type="text/css">
  .gm-style .gm-style-cc span,
  .gm-style .gm-style-cc a,
  .gm-style .gm-style-mtc div {
    font-size:10px
  }
</style>

<link type="text/css" 
      rel="stylesheet" 
      href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700">

<style type="text/css">
  @media print {
    .gm-style .gmnoprint,
    .gmnoprint {
      display:none
    }
  }
  @media screen {
   .gm-style .gmnoscreen,
   .gmnoscreen {
     display:none
   }
  }
</style>
<style type="text/css">
  .gm-style {
    font-family: Roboto,Arial,sans-serif;
    font-size: 11px;
    font-weight: 400;
    text-decoration: none
  }
</style>
Philipp Kyeck
  • 18,402
  • 15
  • 86
  • 123
  • Is that the output? It's hard to tell what the code itself is referencing. – Josh Burgess Sep 16 '14 at 21:29
  • @JoshBurgess yep, this is what google adds to the `` when including the maps-api-javascript – Philipp Kyeck Sep 17 '14 at 05:59
  • Short of using an older version of the gmapsAPI, I can't find a way to prevent Roboto from coming over without blocking requests to that domain from Apache, IIS or whatever equivalent you're using. If that's enough, I'll pop it into an answer, but it seems like a cop-out to me. – Josh Burgess Sep 17 '14 at 21:52
  • @pkyeck, check it out! is working! – coma Sep 18 '14 at 07:45

5 Answers5

80

You can replace the insertBefore method before the Google script invokes it:

http://jsfiddle.net/coma/7st6d9p2/

var head = document.getElementsByTagName('head')[0];

// Save the original method
var insertBefore = head.insertBefore;

// Replace it!
head.insertBefore = function (newElement, referenceElement) {

    if (newElement.href && newElement.href.indexOf('//fonts.googleapis.com/css?family=Roboto') > -1) {

        console.info('Prevented Roboto from loading!');
        return;
    }

    insertBefore.call(head, newElement, referenceElement);
};

// Check it!
new google.maps.Map(document.getElementById('map'), {
    center           : new google.maps.LatLng(51.508742,-0.120850),
    zoom             : 16,
    mapTypeId        : google.maps.MapTypeId.ROADMAP,
    streetViewControl: false,
    zoomControl      : false,
    panControl       : false,
    mapTypeControl   : false
});
coma
  • 16,429
  • 4
  • 51
  • 76
  • thanks for the answer. was hoping for some kind of API-option you could use but this 'hack' definitely works :) – Philipp Kyeck Sep 20 '14 at 19:20
  • I haven't found anything on their docs, guess that they want to preserve its style. Btw, once the font load is prevented, you can revert the change to skip that if on each insertBefore call. – coma Sep 20 '14 at 21:15
  • Great Thanks! Works for me. – Seeker Sep 08 '15 at 14:56
  • This is nice and clever. I'm not sure to understand: does the solution replace the `insertBefore` method specifically for the `` tag? I think I need some explanations about the `insertBefore.call(head, newEl, refEl);` : is this syntax used to make sure we call here the standard ìnsertBefore` , or for another reason? And about the `var insertBefore = head.insertBefore;` : I don't understand what is used for. Thanks in advance, I'm trying to understand. :) – meduz' Apr 03 '16 at 19:04
  • hey @meduz'!, yes, the idea is monkey patching the insertBefore method only for the head DOM node: http://me.dt.in.th/page/JavaScript-override/ – coma Apr 03 '16 at 19:11
  • OK I see. Thank you! – meduz' Apr 04 '16 at 10:27
  • For guys without SSL (https), use http in the link for this to work. – Ayman Salah May 14 '17 at 22:07
  • 4
    @AymanSalah or just use `newElement.href.indexOf('//fonts.googleapis.com/css?family=Roboto') !== -1` which works for both http and https – Salaros Aug 02 '17 at 21:20
  • 5
    This solution doesn't work if the map is embedded using an iframe, because the Roboto font is loaded by a css call in the head section of the iframe document, to which access is prevented. Any hint on that? – Steve Jun 07 '18 at 14:27
  • Works great! Thank you! – fylzero Sep 11 '20 at 18:09
15

UPDATE 10/2017

Google changed the approach of how they inject the styles on the page. Currently they inserting an empty style element and then changing the contents of this style element with Robot font. Here is a new solution:

// Preventing the Google Maps libary from downloading an extra font
(function() {
    var isRobotoStyle = function (element) {

        // roboto font download
        if (element.href
            && element.href.indexOf('https://fonts.googleapis.com/css?family=Roboto') === 0) {
            return true;
        }
        // roboto style elements
        if (element.tagName.toLowerCase() === 'style'
            && element.styleSheet
            && element.styleSheet.cssText
            && element.styleSheet.cssText.replace('\r\n', '').indexOf('.gm-style') === 0) {
            element.styleSheet.cssText = '';
            return true;
        }
        // roboto style elements for other browsers
        if (element.tagName.toLowerCase() === 'style'
            && element.innerHTML
            && element.innerHTML.replace('\r\n', '').indexOf('.gm-style') === 0) {
            element.innerHTML = '';
            return true;
        }
        // when google tries to add empty style
        if (element.tagName.toLowerCase() === 'style'
            && !element.styleSheet && !element.innerHTML) {
            return true;
        }

        return false;
    }

    // we override these methods only for one particular head element
    // default methods for other elements are not affected
    var head = $('head')[0];

    var insertBefore = head.insertBefore;
    head.insertBefore = function (newElement, referenceElement) {
        if (!isRobotoStyle(newElement)) {
            insertBefore.call(head, newElement, referenceElement);
        }
    };

    var appendChild = head.appendChild;
    head.appendChild = function (textNode) {
        if (!isRobotoStyle($(textNode)[0])) {
            appendChild.call(head, textNode);
        }
    };
})();

ORIGINAL ANSWER

Thanks to coma for the solution! I also decided to intercept styles which override the font-family, font-size and font-weight. The complete solution for modern browsers and IE8+:

// Preventing the Google Maps libary from downloading an extra font
var head = $('head')[0];
var insertBefore = head.insertBefore;
head.insertBefore = function (newElement, referenceElement) {
    // intercept font download
    if (newElement.href
        && newElement.href.indexOf('https://fonts.googleapis.com/css?family=Roboto') === 0) {
        return;
    }
    // intercept style elements for IEs
    if (newElement.tagName.toLowerCase() === 'style'
        && newElement.styleSheet
        && newElement.styleSheet.cssText
        && newElement.styleSheet.cssText.replace('\r\n', '').indexOf('.gm-style') === 0) {
        return;
    }
    // intercept style elements for other browsers
    if (newElement.tagName.toLowerCase() === 'style'
        && newElement.innerHTML
        && newElement.innerHTML.replace('\r\n', '').indexOf('.gm-style') === 0) {
        return;
    }
    insertBefore.call(head, newElement, referenceElement);
};
Pavel Morshenyuk
  • 10,891
  • 4
  • 32
  • 38
  • 1
    Magnificent, thanks a lot. You can easily leave out the 2 jQuery references, so it's usable by anyone: `document.getElementsByTagName('head')[0]` instead of `$('head')[0];` `textNode` instead of `$(textNode)[0]` – Vincent Sels Aug 02 '18 at 10:37
2

For TypeScript a solution would be:

const head = document.head;
const insertBefore = head.insertBefore;
head.insertBefore = <T extends Node>(
  newElement: T,
  referenceElement: Node
): T => {
  if (
    newElement instanceof Element &&
    newElement?.hasAttribute('href') &&
    newElement?.getAttribute('href')?.includes('fonts.googleapis')
  ) {
    return newElement;
  }

  insertBefore.call(head, newElement, referenceElement);
  return newElement;
};
S3n
  • 59
  • 7
0

I found above solution to prevent websites with Google Maps from loading Roboto.

If you - like I do - use Wordpress, there might be other plugins referring to Google Fonts.

However, I struggled on some of my websites with the above code, since parts of it (1) affected also other styles to load, (2) "killed" styles, which intentionally not only contained gm-style, but other styles as well and (3) not affected other Google Fonts to load, where one or another plugin added links to fonts.googleapis.com by DOM-manipulation as well.

The below worked for me. It simply prevents other scripts from adding any tag having https://fonts.googleapis.com in it's href-attribute.

(function($) {
var isGoogleFont = function (element) {
    // google font download
    if (element.href
        && element.href.indexOf('https://fonts.googleapis.com') === 0) {
        return true;
    }       
    return false;
}

// we override these methods only for one particular head element
// default methods for other elements are not affected
var head = $('head')[0];

var insertBefore = head.insertBefore;
head.insertBefore = function (newElement, referenceElement) {
    if (!isGoogleFont(newElement)) {
        insertBefore.call(head, newElement, referenceElement);
    }
};

var appendChild = head.appendChild;
head.appendChild = function (textNode) {
    if (!isGoogleFont($(textNode)[0])) {
        appendChild.call(head, textNode);
    }
};
})(jQuery);
Thommy Tomka
  • 332
  • 1
  • 3
  • 14
  • First of all thanks for your code. Unfortunately I can't manage to get this to work. When I add it to the functions.php file of my child theme it says: "syntax error, unexpected '$', expecting variable (T_VARIABLE)" and I can't save the file. Any idea why it doesn't accept $? – Mario Mar 09 '21 at 09:25
  • @Mario Add `var $ = jQuery.noConflict();` to the top and that should fix it for you. – AuRise Dec 23 '22 at 14:51
0

Unfortunately, I'm a newb and I couldn't get the other suggestions to work. So I removed all the Google fonts from the DOM. I hope it helps.

const googleFont = document.querySelector('link[rel="stylesheet"][href*="fonts.googleapis.com"]');
    if (googleFont) {
      googleFont.remove();
    }