How do you define #font-face in a CSSObject? - css

Suppose I have the following #font-face rule(s) and I want to put them as a CSSObject instead of a flat string.
#font-face {
font-family: 'Blah';
font-weight: 400;
font-style: normal;
src:
url('./Blah-Normal.woff2') format('woff2'),
url('./Blah-Normal.woff') format('woff');
}
#font-face {
font-family: 'Blah';
font-weight: 700;
font-style: bold;
src:
url('./Blah-Bold.woff2') format('woff2'),
url('./Blah-Bold.woff') format('woff');
}
...
How can I define it as a CSSObject? I'm trying to pass it over to Mui's MuiCssBaseline and it takes a CSSObject or string. I'd like to pass a CSSObject so that I could add more CSS styling on it more easily and easier to read. But right now it is just a flat string containing only the #font-face definitions.
// import { CSSObject } from '#mui/material';
// import { CSSObject } from '#emotion/styled';
import { CSSObject } from 'styled-components';
const BlahCSSObject = {
'#font-face': {
// magic?
src: [
// it definitely don't like the following format
url('./Blah-Bold.woff2') format('woff2'),
url('./Blah-Bold.woff') format('woff')
]
},
'#font-face': { // would cause dupe keys no?
...
},
...
} as CSSObject;
Thanks!

I think you can use css method from styled-components.
import { css } from 'styled-components'
const myOwnStyle = css`
#font-face {
// styles
}
`

Related

Local font not loading in NextJs

I am trying to load the local font 'Stigfier' through my 'styles/styles.css' global css and it is not loading. My google fonts loaded in the '_document.jsx' work fine.
#font-face {
font-family: Stigfier;
src:
url('/../public/fonts/stigfier/Stigfier.woff') format('woff'),
url('/../public/fonts/stigfier/Stigfier.woff2') format('woff2'),
url('/../public/fonts/stigfier/Stigfier.ttf') format('truetype'),
url('/../public/fonts/stigfier/Stigfier.otf') format('opentype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
body {
font-family: Stigfier;
}
But it is not loading, same with the recommended way in the Nextjs website docs:
import localFont from '#next/font/local'
const stigfier = localFont({src: '/../public/fonts/stigfier/Stigfier.woff2'})
export default function MyApp({ Component, pageProps }) {
return (
<div className={stigfier.className}>
<Component {...pageProps} />
</div>
)
}
and even creating a link in the '_document.jsx' like so:
<link
rel="preload"
href="/../public/fonts/stigfier/Stigfier.ttf"
as="font"
type="font/ttf"
crossOrigin="anonymous"
/>
As your fonts are already in the public folder you do not need to specify it.
#font-face {
font-family: Stigfier;
src:
url('/fonts/stigfier/Stigfier.woff') format('woff'),
url('/fonts/stigfier/Stigfier.woff2') format('woff2'),
url('/fonts/stigfier/Stigfier.ttf') format('truetype'),
url('/fonts/stigfier/Stigfier.otf') format('opentype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
body {
font-family: Stigfier;
}```
In next/font/local, with src you need to add other properties like weight, display and subset.
also make sure you are working on next 13, because next/font is a new feature which comes under nextjs 13.
read this: Nextjs 13 features

Inlining fonts and images inside CSS files with Webpack5?

I need to import into my project some CSS files with Webpack 5 and I need to inline all these resources (it's a requirement sadly). Inside the CSS there are some fonts and images with relative URI, like this:
#font-face { font-family: "MyFont"; src: url(./fonts/Roboto-Regular.ttf) format("truetype"); font-weight: normal;}
#font-face { font-family: "MyFont"; src: url(./fonts/Roboto-Bold.ttf) format("truetype"); font-weight: bold;}
#font-face { font-family: "MyFont"; src: url(./fonts/Roboto-Italic.ttf) format("truetype"); font-weight: normal; font-style: italic;}
#font-face { font-family: "MyFont"; src: url(./fonts/Roboto-BoldItalic.ttf) format("truetype"); font-weight: bold; font-style: italic;}
#font-face { font-family: 'Material Icons'; font-style: normal; font-weight: 400; src: url(./fonts/material-icons.woff2) format('woff2'); }
#font-face { font-family: 'Material Icons Outlined'; font-style: normal; font-weight: 400; src: url(./fonts/material-icons-outlined.woff2) format('woff2'); }
* { font-family: "MyFont", "Roboto-Light", "Noto Sans CJK SC", "DejaVu Sans"; }
.UICheckbox { width:80px; height:89px; background-image:url("img/checkboxOFF.png"); background-repeat:no-repeat; }
.UICheckbox.checked { background-image:url("img/checkboxON.png"); }
Since I need to import as base64 the CSS files I cannot actually process automatically the resources found inside of them (contrary to how it is done with PostCSS or similiars).
My current webpack configuration is the following but it just ignores the url() statements:
{
test: /\.(png|jpg|gif)$/i,
type: "asset/inline",
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: "asset/inline",
},
{
test: /\.css$/i,
type: "asset/inline",
},
Is there a better way to handle this?
I found a solution that is not really generic or solid but does the job, at least in my case scenario.
The imports are relatives to a fixed source path so the idea is to read the resources found inside the url() rules and process it as DataURI in base64 encoding.
I found quite useful the use of datauri which provides a way to include data in-line as if they were external resources and manages the mimetypes automatically.
npm install datauri --save
Then I had to modify the generator handler inside webpack.config.js to process the resources manually exploiting the datauri package.
const path = require("path");
const Datauri = require("datauri/sync");
const EXTERNAL_ROOT_PATH = "./src/external/dev/";
module.exports = {
...
module: {
rules: [
{
test: /\.css$/i,
type: "asset/inline",
generator: {
dataUrl: (content) => {
content = content.toString();
// Get the resource paths inside the CSS url() rules
let asset_urls = [];
let match,
regex = /url\((.*?)\)/gi;
while ((match = regex.exec(content))) {
asset_urls.push(match[1]);
}
// console.log(asset_urls);
// Convert the resource to a DataURI and replace it inside url()
asset_urls.forEach((file_path) => {
// Sanitize the file path first
sanitized_file_path = file_path.replace(/[\"\']/g, "").replace(/^(?:\.\.\/)+/, "");
const data_uri = Datauri(path.join(EXTERNAL_ROOT_PATH, sanitized_file_path));
// console.log(data_uri.content); //=> "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
// console.log(data_uri.mimetype); //=> "image/png"
// console.log(data_uri.base64); //=> "iVBORw0KGgoAAAANSUhEUgAA..."
// console.log(data_uri.buffer); //=> file buffer
content = content.replace(file_path, data_uri.content);
});
return "data:text/css;base64," + Buffer.from(content).toString("base64");
},
},
},
],
},
};

Load local fonts in vite vue3 project

In main.scss I load local fonts from assets/styles/fonts folder:
#font-face {
font-family: 'Opensans-Bold';
font-style: normal;
src: local('Opensans-Bold'), url(./fonts/OpenSans-Bold.ttf) format('truetype');
}
#font-face {
font-family: 'Opensans-Light';
font-style: normal;
src: local('Opensans-Light'), url(./fonts/OpenSans-Light.ttf) format('truetype');
}
then in vite.config I load main.scss:
css: {
preprocessorOptions: {
scss: {
additionalData: `#import "#/assets/styles/main.scss";`
}
}
},
but all css from main.scss is applied except fonts, I get error:
downloadable font: download failed (font-family: "Opensans-Bold" style:normal weight:400 stretch:100 src index:1): status=2152398850 source: http://localhost:3000/fonts/OpenSans-Bold.ttf
Am I on right track or I need some other approach (similar works with Vue-CLI)?
That was the right way, the solution is the relative path so:
src: local('Opensans-Bold'), url(#/assets/styles/fonts/OpenSans-Bold.ttf) format('truetype');
and setting alias in vite.config.js :
resolve: {
alias: {
'#': path.resolve(__dirname, 'src'),
}
}
I was able to make this work by simply put the fonts on a public folder on root.
like:
public/.**.ttf
src/

Custom fonts with L.divIcon Leaflet not showing

Using the icomoon internet service to create custom icon-fonts, having trouble to make them visible on Leaflet map. Somehow I can not fetch the icons, what have I missed!? I have the data on the map as I can open up the popup, the problem is there is no icons visible....
I have the fonts folder in the correct place and stylesheet is loaded
This is part of the CSS from icomoon I have in a custom-style.css
#font-face {
font-family: 'icomoon';
src: url('myplace/customer/fonts/icomoon.eot?bf4cat');
src: url('myplace/customer/fonts/icomoon.eot?bf4cat#iefix') format('embedded-opentype'),
url('myplace/customer/fonts/icomoon.ttf?bf4cat') format('truetype'),
url('myplace/customer/fonts/icomoon.woff?bf4cat') format('woff'),
url('myplace/customer/fonts/icomoon.svg?bf4cat#icomoon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
[class^="icon-"], [class*=" icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'icomoon' !important;
speak: never;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-bb .path1:before {
content: "\e900";
color: rgb(35, 31, 32);
}
.icon-bb .path2:before {
content: "\e901";
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-bb .path3:before {
content: "\e902";
margin-left: -1em;
color: rgb(0, 0, 0);
} etc....
Then I created a function to look for customer name and give them a className
function getCustomer(x){
x === 'customerBB' ? 'icon- icon-bb' :
x === 'customerCA' ? 'icon- icon-ca' :
x === 'customerCE' ? 'icon- icon-ce' :
'leaflet-div-icon'; //default blue icon if no match
Then a function to return className depending on the results found in feature.properties.customer_name
var setDivIcon = function(feature){
return {
className: getCustomer(feature.properties.customer_name)
};
}
var customerIcon = L.divIcon(setDivIcon);
Later on I use the pointToLayer to add the GeoJSON to the map
customerLayer = L.geoJson(json, {
pointToLayer: function(feature, latlng) {
var time = feature.properties.timeMean_numb;
var point
if (time < 0.167){
point = L.marker(latlng, {icon: L.divIcon(setDivIcon(feature)) }).addTo(time_1);
}
else if (time >= 0.167 && time <= 0.334){
point = L.marker(latlng, {icon: L.divIcon(setDivIcon(feature)) }).addTo(time_2);
}
In your fontface rule you are missing some src:? This could explain them not being fetched

Font-face not working at all

I've read a lot of posts and make my font-face code same as in other answers and it's still not working...
#font-face {
font-family: 'KlavikaLT';
src: url('Klavika-Light.otf') format('opentype');
}
#font-face {
font-family: 'KlavikaLTit';
src: url('Klavika-LightItalic.otf') format('opentype');
}
#font-face {
font-family: 'KlavikaBD';
src: url('Klavika-Bold.otf') format('opentype');
}
#font-face {
font-family: 'KlavikaBDit';
src: url('Klavika-BoldItalic.otf') format('opentype');
}
#font-face {
font-family: 'KlavikaRG';
src: url('Klavika-Regular.otf') format('opentype');
}
.footerleft
{
font-family: KlavikaLT;
}
.footerright
{
font-family: KlavikaBDit;
}
This is my example code that I use. Fonts are in the same folder as stylesheet file. Where do I make a mistake?
EDIT 1
It's funny because it's working on my localhost and all paths are correct. Not working on my server, but I made the same as in my code on other my site and it's working there...
Use this syntax:
<style>
#font-face {
font-family: 'KlavikaLT';
src: url('KlavikaLT.eot');
src: url('KlavikaLT.eot?#iefix') format('embedded-opentype'),
url('KlavikaLT.woff') format('woff'),
url('KlavikaLT.ttf') format('truetype'),
url('KlavikaLT.svg#KlavikaLT') format('svg');
font-weight: normal;
font-style: normal;
}
body { font-family: "KlavikaLT", serif; }
</style>
Make sure the file paths are correct.
This is the specification for #font-face:
#font-face {
[font-family: <family-name>;]?
[src: [ <uri> [format(<string>#)]? | <font-face-name> ]#;]?
[unicode-range: <urange>#;]?
[font-variant: <font-variant>;]?
[font-feature-settings: normal|<feature-tag-value>#;]?
[font-stretch: <font-stretch>;]?
[font-weight: <weight>];
[font-style: <style>];
}
'KlavikaLT' is not a standard font like Courier for example. Your browser has no idea what that font is unless you tell it.
You can tell the browser about your font in a couple of ways:
Post the import at the top of your css:
#import url(https://fonts.googleapis.com/css?family=Open+Sans);
Import with HTML, above your CSS:
<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
Or using JavaScript:
<script type="text/javascript">
WebFontConfig = {
google: { families: [ 'Open+Sans::latin' ] }
};
(function() {
var wf = document.createElement('script');
wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
'://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
wf.type = 'text/javascript';
wf.async = 'true';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
})(); </script>
Examples copied from Google Fonts.
If you're using a custom font hosted on your own server, you can use the above syntax, but replace the urls with your own. Each one should contain the #font-face, which looks like this:
#font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format('woff2');
}
Just added more extensions of font, like .ttf and .woff. Now it's working perfectly, but don't know why .otf doesn't work at all. Cheers!
#font-face
{
font-family: KlavikaLT;
src: url('fonts/KlavikaLT.otf') format('opentype'),
url('fonts/KlavikaLT.ttf') format('truetype'),
url('fonts/KlavikaLT.woff') format('woff');
}

Resources