I need to use some google fonts on an intranet application. The clients may or may not have internet connection. Reading the license terms, it appears that its legally allowed.
Please keep in mind that my answer has aged a lot.
There are other more technically sophisticated answers below, e.g.:
so don't let the fact that this is the currently accepted answer give you the impression that this is still the best one.
You can also now also download google's entire font set via on github at their google/font repository. They also provide a ~1GB zip snapshot of their fonts.
You first download your font selection as a zipped package, providing you with a bunch of true type fonts. Copy them somewhere public, somewhere you can link to from your css.
On the google webfont download page, you'll find a include link like so:
http://fonts.googleapis.com/css?family=Cantarell:400,700,400italic,700italic|Candal
It links to a CSS defining the fonts via a bunch of @font-face
defintions.
Open it in a browser to copy and paste them into your own CSS and modify the urls to include the right font file and format types.
So this:
@font-face {
font-family: 'Cantarell';
font-style: normal;
font-weight: 700;
src: local('Cantarell Bold'), local('Cantarell-Bold'), url(http://themes.googleusercontent.com/static/fonts/cantarell/v3/Yir4ZDsCn4g1kWopdg-ehHhCUOGz7vYGh680lGh-uXM.woff) format('woff');
}
becomes this:
/* Your local CSS File */
@font-face {
font-family: 'Cantarell';
font-style: normal;
font-weight: 700;
src: local('Cantarell Bold'), local('Cantarell-Bold'), url(../font/Cantarell-Bold.ttf) format('truetype');
}
As you can see, a downside of hosting the fonts on your own system this way is, that you restrict yourself to the true type format, whilst the google webfont service determines by the accessing device which formats will be transmitted.
Furthermore, I had to add a .htaccess
file to my the directory holding the fonts containing mime types to avoid errors from popping up in Chrome Dev Tools.
For this solution, only true type is needed, but defining more does not hurt when you want to include different fonts as well, like font-awesome
.
#.htaccess
AddType application/vnd.ms-fontobject .eot
AddType font/ttf .ttf
AddType font/otf .otf
AddType application/x-font-woff .woff
Great solution is google-webfonts-helper .
It allows you to select more than one font variant, which saves a lot of time.
latin-ext
fonts too. –
Enliven I wrote a bash script that fetches the CSS file on Google's servers with different user agents, downloads the different font formats to a local directory and writes a CSS file including them. Note that the script needs Bash version 4.x.
See https://neverpanic.de/blog/2014/03/19/downloading-google-web-fonts-for-local-hosting/ for the script (I'm not reproducing it here so I only have to update it in one place when I need to).
Edit: Moved to https://github.com/neverpanic/google-font-download
The contents of the CSS file (from the include URL) depends on what browser I view it from. For example, when browsing to http://fonts.googleapis.com/css?family=Open+Sans using Chrome, the file only contained WOFF links. Using Internet Explorer (below), it included both EOT and WOFF. I pasted all the links into my browser to download them.
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: url(http://themes.googleusercontent.com/static/fonts/opensans/v6/cJZKeOuBrn4kERxqtaUH3fY6323mHUZFJMgTvxaG2iE.eot);
src: local('Open Sans'), local('OpenSans'), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/cJZKeOuBrn4kERxqtaUH3fY6323mHUZFJMgTvxaG2iE.eot) format('embedded-opentype'), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/cJZKeOuBrn4kERxqtaUH3T8E0i7KZn-EPnyo3HZu7kw.woff) format('woff');
}
When you host your own web fonts, you need to correctly link to each font type, deal with legacy browser bugs, etc. When you use Google Web Fonts (hosted by Google), Google automatically links to the correct font types for that browser.
It is legally allowed as long as you stick to the terms of the font's license - usually the OFL.
You'll need a set of web font formats, and the Font Squirrel Webfont Generator can produce these.
But the OFL required the fonts be renamed if they are modified, and using the generator means modifying them.
I have a script written in PHP similar to that of @neverpanic that automatically downloads both the CSS and fonts (both hinted and unhinted) from Google. It then serves the correct CSS and fonts from your own server based on the User Agent. It keeps its own cache, so fonts and CSS of a User Agent will only be downloaded once.
It's in a premature stage, but it can be found here: DaAwesomeP / php-offline-fonts
Easiest Approach - Using google-webfonts-helper
Lets say we want to host the font Red Rose
:
- Open google-webfonts-helper and filter for the required font on top left (type Red Rose and enter..)
- Choose from the charsets (default is latin; select others like latin-ext if you want extended support)
- Select the styles (deafult is regular)
- From the
Copy CSS
tab- Select
Modern Browser
if you wish to support only modern browsers (woff2, woff) - Select
Best Support
if you wish to support all browsers (I chose this - woff2, woff,ttf,svg,eot)
- Select
- In case your font files do not reside in
../fonts/
path, you can edit it to represent your actual path (for me it was../assets/fonts/
) - Copy the CSS and keep for future use
- Download the zip file named
red-rose-v1-latin-ext_latin
; unzip it and place all fonts directly into yourassets/fonts
directory (based on what you gave earlier) - In your stylesheet where you wish to embed, paste the copied CSS. It will look like the below if you chose these options
/* red-rose-regular - latin-ext_latin */
@font-face {
font-family: 'Red Rose';
font-style: normal;
font-weight: 400;
src: url('../assets/fonts/red-rose-v1-latin-ext_latin-regular.eot'); /* IE9 Compat Modes */
src: local('Red Rose Regular'), local('RedRose-Regular'),
url('../assets/fonts/red-rose-v1-latin-ext_latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('../assets/fonts/red-rose-v1-latin-ext_latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
url('../assets/fonts/red-rose-v1-latin-ext_latin-regular.woff') format('woff'), /* Modern Browsers */
url('../assets/fonts/red-rose-v1-latin-ext_latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
url('../assets/fonts/red-rose-v1-latin-ext_latin-regular.svg#RedRose') format('svg'); /* Legacy iOS */
}
/* Red Rose will now be available for use in your stylesheet, provide this font */
:root {
font-family: 'Red Rose', cursive, sans-serif;
}
- Thats ALL!
You can actually download all font format variants directly from Google and include them in your css to serve from your server. That way you don't have to concern about Google tracking your site's users. However, the downside maybe slowing down your own serving speed. Fonts are quite demanding on resources. I have not done any tests in this issue yet, and wonder if anyone has similar thoughts.
As you want to host all fonts (or some of them) at your own server, you a download fonts from this repo and use it the way you want: https://github.com/praisedpk/Local-Google-Fonts
If you just want to do this to fix the leverage browser caching issue that comes with Google Fonts, you can use alternative fonts CDN, and include fonts as:
<link href="https://pagecdn.io/lib/easyfonts/fonts.css" rel="stylesheet" />
Or a specific font, as:
<link href="https://pagecdn.io/lib/easyfonts/lato.css" rel="stylesheet" />
Edit: As luckyrumo pointed out, typefaces is depricated in favour of: https://github.com/fontsource/fontsource
If you're using Webpack, you might be interested in this project: https://github.com/KyleAMathews/typefaces
E.g. say you want to use Roboto font:
npm install typeface-roboto --save
Then just import it in your app's entrypoint (main js file):
import 'typeface-roboto'
I used grunt-local-googlefont in a grunt task.
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
"local-googlefont" : {
"opensans" : {
"options" : {
"family" : "Open Sans",
"sizes" : [
300,
400,
600
],
"userAgents" : [
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)", //download eot
"Mozilla/5.0 (Linux; U; Android 4.1.2; nl-nl; GT-I9300 Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", //download ttf
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1944.0 Safari/537.36" //download woff and woff2
],
"cssDestination" : "build/fonts/css",
"fontDestination" : "build/fonts",
"styleSheetExtension" : "css",
"fontDestinationCssPrefix" : "fonts"
}
}
}
});
grunt.loadNpmTasks('grunt-local-googlefont');
};
Then, to retrieve them:
grunt local-googlefont:opensans
Note, I'm using a fork from the original, which works better when retrieving fonts with whitespaces in their names.
You may follow the script which is developed using PHP.
Where you can download any google fonts by using the script.
It will download the fonts and create a CSS file and archive to zip.
You can download the source code from the GitHub https://github.com/souravmsh/google-fonts-downloader
$obj = new GoogleFontsDownloader;
if(isset($_GET['url']) && !empty($_GET['url']))
{
$obj->generate($_GET['url']);
}
if(isset($_GET['download']) && !empty($_GET['download']) && $_GET['download']=='true')
{
$obj->download();
}
/**
* GoogleFontsDownloader
* Easy way to download any google fonts.
* @author Shohrab Hossain
* @version 1.0.0
*/
class GoogleFontsDownloader
{
private $url = '';
private $dir = 'dist/';
private $fontsDir = 'fonts/';
private $cssDir = 'css/';
private $fileName = 'fonts.css';
private $content = '';
private $errors = '';
private $success = '';
public $is_downloadable = false;
public function __construct()
{
ini_set('allow_url_fopen', 'on');
ini_set('allow_url_include', 'on');
}
public function generate($url = null)
{
if (filter_var($url, FILTER_VALIDATE_URL) === FALSE)
{
$this->errors .= "<li><strong>Invalid url!</strong> $url</li>";
}
else
{
$this->url = $url;
// delete previous files
$this->_destroy();
// write font.css
$this->_css();
// write fonts
$this->_fonts();
// archive files
$this->_archive();
}
// show all messages
$this->_message();
}
public function download()
{
// Download the created zip file
$zipFileName = trim($this->dir, '/').'.zip';
if (file_exists($zipFileName))
{
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename = $zipFileName");
header("Pragma: no-cache");
header("Expires: 0");
readfile("$zipFileName");
// delete file
unlink($zipFileName);
array_map('unlink', glob("$this->dir/*.*"));
rmdir($this->dir);
}
}
private function _archive()
{
if (is_dir($this->dir))
{
$zipFileName = trim($this->dir, '/').'.zip';
$zip = new \ZipArchive();
if ($zip->open($zipFileName, ZipArchive::CREATE) === TRUE)
{
$zip->addGlob($this->dir. "*.*");
$zip->addGlob($this->dir. "*/*.*");
if ($zip->status == ZIPARCHIVE::ER_OK)
{
$this->success .= '<li>Zip create successful!</li>';
$this->is_downloadable = true;
}
else
{
$this->errors .= '<li>Failed to create to zip</li>';
}
}
else
{
$this->errors .= '<li>ZipArchive not found!</li>';
}
$zip->close();
}
else
{
$this->errors .= "<li><strong>File</strong> not exists!</li>";
}
}
private function _css()
{
$filePath = $this->dir.$this->cssDir.$this->fileName;
$content = $this->_request($this->url);
if (!empty($content))
{
if (file_put_contents($filePath, $content))
{
$this->success .= "<li>$this->fileName generated successful!</li>";
$this->content = $content;
}
else
{
$this->errors .= '<li>Permission errro in $this->fileName! Unable to write $filePath.</li>';
}
}
else
{
$this->errors .= '<li>Unable to create fonts.css file!</li>';
}
}
private function _fonts()
{
if (!empty($this->content))
{
preg_match_all('#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#', $this->content, $match);
$gFontPaths = $match[0];
if (!empty($gFontPaths) && is_array($gFontPaths) && sizeof($gFontPaths)>0)
{
$count = 0;
foreach ($gFontPaths as $url)
{
$name = basename($url);
$filePath = $this->dir.$this->fontsDir.$name;
$this->content = str_replace($url, '../'.$this->fontsDir.$name, $this->content);
$fontContent = $this->_request($url);
if (!empty($fontContent))
{
file_put_contents($filePath, $fontContent);
$count++;
$this->success .= "<li>The font $name downloaded!</li>";
}
else
{
$this->errors .= "<li>Unable to download the font $name!</li>";
}
}
file_put_contents($this->dir.$this->cssDir.$this->fileName, $this->content);
$this->success .= "<li>Total $count font(s) downloaded!</li>";
}
}
}
private function _request($url)
{
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_HEADER => FALSE,
CURLOPT_FOLLOWLOCATION => TRUE,
CURLOPT_URL => $url,
CURLOPT_REFERER => $url,
CURLOPT_RETURNTRANSFER => TRUE,
));
$result = curl_exec($ch);
curl_close($ch);
if (!empty($result))
{
return $result;
}
return false;
}
private function _destroy()
{
$cssPath = $this->dir.$this->cssDir.$this->fileName;
if (file_exists($cssPath) && is_file($cssPath))
{
unlink($cssPath);
}
else
{
mkdir($this->dir.$this->cssDir, 0777, true);
}
$fontsPath = $this->dir.$this->fontsDir;
if (!is_dir($fontsPath))
{
mkdir($fontsPath, 0777, true);
}
else
{
array_map(function($font) use($fontsPath) {
if (file_exists($fontsPath.$font) && is_file($fontsPath.$font))
{
unlink($fontsPath.$font);
}
}, glob($fontsPath.'*.*'));
}
}
private function _message()
{
if (strlen($this->errors)>0)
{
echo "<div class='alert alert-danger'><ul>$this->errors</ul></div>";
}
if (strlen($this->success)>0)
{
echo "<div class='alert alert-success'><ul>$this->success</ul></div>";
}
}
}
You can download source fonts from https://github.com/google/fonts
After that use font-ranger
tool to split your large Unicode font into multiple subsets (e.g. latin, cyrillic). You should do the following with the tool:
- Generate subsets for each language you support
- Use unicode-range subsetting for saving bandwidth
- Remove bloat from your fonts and optimize them for web
- Convert your fonts to a compressed woff2 format
- Provide .woff fallback for older browsers
- Customize font loading and rendering
- Generate CSS file with @font-face rules
- Self-host web fonts or use them locally
Font-Ranger: https://www.npmjs.com/package/font-ranger
P.S. You can also automate this using Node.js API
© 2022 - 2024 — McMap. All rights reserved.