{"id":16,"date":"2021-09-17T01:05:09","date_gmt":"2021-09-17T01:05:09","guid":{"rendered":"https:\/\/webaffair.net\/blog\/?p=16"},"modified":"2024-06-02T05:55:35","modified_gmt":"2024-06-02T05:55:35","slug":"automatically-generate-google-fonts-link","status":"publish","type":"post","link":"https:\/\/webaffair.net\/blog\/code\/snippets\/automatically-generate-google-fonts-link\/","title":{"rendered":"Automatically generate Google Fonts link."},"content":{"rendered":"\n<p>Useful if you are making a customizable skin, or if you allow users to set font preferences in their account settings.<\/p>\n\n\n\n<p>Of course, the basic way you include google fonts on your page is like this:<\/p>\n\n\n\n<p>HTML (preconnects are technically optional):<\/p>\n\n\n\n<pre class=\"wp-block-code html\"><code>&lt;link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\"&gt;\n&lt;link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin&gt;\n&lt;link href=\"FONT SPECIFIC LINK\" rel=\"stylesheet\"&gt;<\/code><\/pre>\n\n\n\n<p>Or, CSS Include:<\/p>\n\n\n\n<pre class=\"wp-block-code css\"><code>@import url('FONT SPECIFIC LINK');<\/code><\/pre>\n\n\n\n<p>So how to generate that link from an array of font names?<\/p>\n\n\n\n<p>Well, here it is in javascript, which can be used either in node.js or in browser-side javascript with a bit of extra code to create a &lt;link&gt; dom element on the fly:<\/p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>const googleFonts = { \n  \/* 'Font Name': &#91;] \/\/default weight only\n   * or 'Font Name': &#91;list normal weights]\n   * or 'Font Name': &#91;&#91;list normal weights], &#91;list italic weights]] *\/\n  'Poiret One' => &#91;],\n  'Merriweather' => &#91;&#91;400, 700, 900], &#91;400, 700, 900]],\n  'Roboto' => &#91;300, 400],\n} \n\nlet googleFontURL = \"https:\/\/fonts.googleapis.com\/css2?\"; \n\nObject.keys(googleFonts).forEach((key) => { \n  element = googleFonts&#91;key];\n  if (element.length == 0) googleFontURL += `family=${key}&amp;`; \n  else if (!Array.isArray(element&#91;0])) googleFontURL += `family=${key}:wgt@${element.join(';')}&amp;`; \n  else if (element&#91;0].length == 0) googleFontURL += `family=${key}:ital,wgt@01,${element&#91;1].join(';0,')}&amp;`; \n  else googleFontURL += `family=${key}:ital,wgt@0,${element&#91;0].join(';0,')};1,${element&#91;1].join(';0,')}&amp;`; }); \n\ngoogleFontURL += \"display=swap\";<\/code><\/pre>\n\n\n\n<p>And in PHP (for WordPress templates, for example):<\/p>\n\n\n\n<pre class=\"wp-block-code php\"><code>$googleFonts = &#91;\n  \/* 'Font Name': &#91;] \/\/default weight only\n   * or 'Font Name': &#91;list normal weights]\n   * or 'Font Name': &#91;&#91;list normal weights], &#91;list italic weights]] *\/\n  'Poiret One' => &#91;],\n  'Merriweather' => &#91;&#91;400, 700, 900], &#91;400, 700, 900]],\n  'Roboto' => &#91;300, 400],\n];\n\nfunction google_webfonts_link($googleFonts)\n{\n  $googleFontURL = \"https:\/\/fonts.googleapis.com\/css2?\";\n  foreach ($googleFonts as $key => $sizes) {\n    if (!is_array($sizes)) { \n      \/\/assume someone just put in a plain array of font names\n      $googleFontURL .= \"family=\" . str_replace(\" \", \"+\", $sizes) . \"&amp;\"; \n    } \n    else if (count($sizes) == 0) {\n      $googleFontURL .= \"family=\" . str_replace(\" \", \"+\", $key) . \"&amp;\";\n    } else if (!is_array($sizes&#91;0])) {\n      $googleFontURL .= \"family=\" . str_replace(\" \", \"+\", $key) . \":wgt@\" . implode(';', $sizes) . \"&amp;\";\n    } else if (is_array($sizes&#91;0]) &amp;&amp; count($sizes&#91;0]) == 0) {\n      $googleFontURL .= \"family=\" . str_replace(\" \", \"+\", $key) . \":ital,wgt@01,\" . implode($sizes&#91;1], \";0,\") . \"&amp;\";\n    } else {\n      $googleFontURL .= \"family=\" . str_replace(\" \", \"+\", $key) . \":ital,wgt@0,\" . implode(';0,', $sizes&#91;0]) . \";1,\" . implode(';1,', $sizes&#91;1]) . \"&amp;\";\n    }\n  }\n  $googleFontURL .= \"display=swap\";\n  return $googleFontURL;\n}<\/code><\/pre>\n\n\n\n<p>(Yeah, I could use string interpolation, but my php syntax highlighter doesn&#8217;t handle {..} style interpolation. That&#8217;s what you get for using free software.)<\/p>\n\n\n\n<p>WordPress note: php will strip out duplicate query string parameters once it knows it&#8217;s a url, so adding a version to wp_enque_styles will ruin your google fonts link.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Useful if you are making a customizable skin, or if you allow users to set font preferences in their account settings. Of course, the basic way you include google fonts on your page is like this: HTML (preconnects are technically optional): Or, CSS Include: So how to generate that link from an array of font&#8230; <a class=\"read-more\" href=\"https:\/\/webaffair.net\/blog\/code\/snippets\/automatically-generate-google-fonts-link\/\">Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[27],"tags":[16,19],"class_list":["post-16","post","type-post","status-publish","format-standard","hentry","category-snippets","tag-node-js","tag-php"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":250,"url":"https:\/\/webaffair.net\/blog\/code\/basics\/responsive-font-sizes-title-bars\/","url_meta":{"origin":16,"position":0},"title":"Responsive Font Sizes &amp; Title Bars","author":"Jay","date":"November 20, 2025","format":false,"excerpt":"Let's say we want a reall big, chunky main title for our forum skin. Here's, I think, the simplest way to do it, I see this a lot: .maintitle { height: 160px; line-height: 160px; text-align: center; font-size: 40px; } If we add that to the stylesheet and check it on\u2026","rel":"","context":"In &quot;Basics&quot;","block_context":{"text":"Basics","link":"https:\/\/webaffair.net\/blog\/category\/code\/basics\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/11\/responsive-font-sizes-step10-desktop.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/11\/responsive-font-sizes-step10-desktop.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/11\/responsive-font-sizes-step10-desktop.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/11\/responsive-font-sizes-step10-desktop.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/11\/responsive-font-sizes-step10-desktop.jpg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":317,"url":"https:\/\/webaffair.net\/blog\/code\/basics\/introduction-to-browser-development-tools\/","url_meta":{"origin":16,"position":1},"title":"Introduction to Browser Development Tools","author":"Jay","date":"December 18, 2025","format":false,"excerpt":"All modern desktop browsers now have integrated browser tools, however, there are subtle (and sometimes less subtle) differences between each. I find that Firefox has the best overall, though I do switch to Chrome for some specific debugging tasks. I personally only use Edge or Safari when trying to isolate\u2026","rel":"","context":"In &quot;Basics&quot;","block_context":{"text":"Basics","link":"https:\/\/webaffair.net\/blog\/category\/code\/basics\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2025\/12\/DevToolsSettingsFirefox-1-scaled.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":9,"url":"https:\/\/webaffair.net\/blog\/code\/basics\/funky-cursor-colours\/","url_meta":{"origin":16,"position":2},"title":"Changing the Colors of Input Elements","author":"Jay","date":"September 16, 2021","format":false,"excerpt":"Ever been on a forum site with a really nice dark theme, but then you go to make a post, and are presented with a large blindingly white text area to type in? Maybe with tiny, hard to read font? Of course you have. But this is a 100% fixable\u2026","rel":"","context":"In &quot;Basics&quot;","block_context":{"text":"Basics","link":"https:\/\/webaffair.net\/blog\/category\/code\/basics\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":49,"url":"https:\/\/webaffair.net\/blog\/code\/snippets\/my-favourite-text-gradients\/","url_meta":{"origin":16,"position":3},"title":"My Favourite Text Gradients","author":"Jay","date":"September 26, 2021","format":false,"excerpt":"Note: I am using -webkit prefixed styles for all three relevant rules to ensure that only browsers that implement all three will load the background gradient at all. I could use a proper polyfill and\/or @supports, but honestly this creates more readable code. Non-webkit browsers have started using webkit prefixes\u2026","rel":"","context":"In &quot;Snippets and Notes&quot;","block_context":{"text":"Snippets and Notes","link":"https:\/\/webaffair.net\/blog\/category\/code\/snippets\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":137,"url":"https:\/\/webaffair.net\/blog\/code\/basics\/ajax-and-images\/","url_meta":{"origin":16,"position":4},"title":"AJAX and Images","author":"Jay","date":"June 22, 2024","format":false,"excerpt":"Okay so I recently figured this out, fixed it on my scripts, forgot about it, was just reminded, realized I ought to document\/share. So this is getting posted here and a couple other places. When you do a fetch() or $.get() the browser only fetches that specific page, and doesn't\u2026","rel":"","context":"In &quot;Basics&quot;","block_context":{"text":"Basics","link":"https:\/\/webaffair.net\/blog\/category\/code\/basics\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":115,"url":"https:\/\/webaffair.net\/blog\/code\/basics\/using-svg-filters-in-css\/","url_meta":{"origin":16,"position":5},"title":"Using SVG Filters in CSS","author":"Jay","date":"June 2, 2024","format":false,"excerpt":"Firstly, you'll need the svg itself. <svg style=\"height:0; overflow:hidden;\"> <defs> <filter id=\"wavy2\"> <feTurbulence x=\"0\" y=\"0\" baseFrequency=\"0.02\" numOctaves=\"5\" seed=\"1\"><\/feTurbulence> <feDisplacementMap in=\"SourceGraphic\" scale=\"20\"><\/feDisplacementMap> <\/filter> <filter id=\"goo\"><feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"8\" result=\"blur\"><\/feGaussianBlur> <feColorMatrix in=\"blur\" mode=\"matrix\" values=\"1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9\"\u2026","rel":"","context":"In &quot;Basics&quot;","block_context":{"text":"Basics","link":"https:\/\/webaffair.net\/blog\/category\/code\/basics\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2024\/06\/filter2.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2024\/06\/filter2.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/webaffair.net\/blog\/wp-content\/uploads\/2024\/06\/filter2.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/posts\/16","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/comments?post=16"}],"version-history":[{"count":5,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/posts\/16\/revisions"}],"predecessor-version":[{"id":47,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/posts\/16\/revisions\/47"}],"wp:attachment":[{"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/media?parent=16"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/categories?post=16"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webaffair.net\/blog\/wp-json\/wp\/v2\/tags?post=16"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}