I am working on a react application and trying to implement CSS + Fonts.
In my react component CSS file I have regular CSS and at the very top I import my mixins
#import '../../mixins.css';
/*CSS*/
Inside my mixin file I have
mixin.css
#font-face {
font-family: 'SourceSansPro-Black';
src: url("./SourceSansPro-Black.ttf") format('truetype');
font-weight: normal;
font-style: normal;
}
Webpack throws an error
Error: Cannot resolve 'file' or 'directory' ./SourceSansPro-Black.ttf
This is my webpack config module loadres
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel',
include: [
path.resolve(__dirname, 'src/app')
]
},
{
test: /\.css$/,
include: [
path.resolve(__dirname, 'src/app/styles'),
path.resolve(__dirname, 'src/app/components')
],
loader: combineLoaders([
{
loader: 'style'
},
{
loader: 'css',
query: {
modules: true,
sourceMap: true,
localIdentName: '[folder]__[local]--[hash:base64:10]'
}
},
{
loader: 'postcss'
}
])
},
// Font Definitions
{
test: /\.ttf$/,
include: [
path.resolve(__dirname, 'src/app/assets/fonts')
],
loader: 'url',
query: {
limit: 50000,
mimetype: 'application/octet-stream',
name: './fonts/[name].[ext]'
}
}
]
},
and the postcss
postcss: (_webpack) => {
return [
require('postcss-import')({
addDependencyTo: _webpack,
path: [ 'styles', 'components'],
root: path.resolve(__dirname, 'src/app'),
skipDuplicates: true
}),
require('postcss-cssnext')()
];
},
I dont' understand why the url isn't resolving correctly.
UPDATE
I have a font.css file that looks like this
#font-face {
font-family: 'SourceSansPro-Bold';
src: url('./SourceSansPro-Bold.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
#font-face {
font-family: 'SourceSansPro-Regular';
src: url('./SourceSansPro-Regular.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
#font-face {
font-family: 'SourceSansPro-Light';
src: url('./SourceSansPro-Light.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
I then import the font.css into a mixins.css file
#import '../fonts/fonts.css';
:root {
--regular: {
font-family: 'SourceSansPro-Regular';
font-style: normal;
font-weight: normal;
}
}
Then in my react component I have this:
#import 'styles/mixins.css';
.regular {
#apply --regular;
}
There is no error (or warning) that states any issues with loading the fonts via the url().
webpack.config
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel',
include: [
path.resolve(__dirname, 'src/app')
]
},
{
test: /\.css$/,
include: [
path.resolve(__dirname, 'src/app/assets/fonts'),
path.resolve(__dirname, 'src/app/assets/styles'),
path.resolve(__dirname, 'src/app/components')
],
loader: combineLoaders([
{
loader: 'style',
},
{
loader: 'css',
query: {
modules: true,
sourceMap: true,
localIdentName: '[folder]__[local]--[hash:base64:10]'
}
},
{
loader: 'resolve-url',
query: {
sourceMap: true,
silent: false,
fail: true,
keepQuery: true
}
},
{
loader: 'postcss',
query: {
sourceMap: true
}
}
])
},
// Font Definitions
{
test: /\.ttf$/,
include: [
path.resolve(__dirname, 'src/app/assets/fonts')
],
loader: 'url',
query: {
limit: 100000,
mimetype: 'application/octet-stream',
name: './fonts/[name].[ext]'
}
}
]
}
An interesting thing is that if I use the ExtractTextWebpackPlugin on the CSS the above works, the fonts get rendered. If I do it this way the tradeOff is there is no CSS hot reloading.
Any suggestions on how to get the fonts to load without the extract-text plugin?
Related
I'm using css modules with sass. So i try to load them like this:
#font-face {
font-family: 'Book Antiqua';
src: url(#/assets/fonts/book_antiqua.ttf) format('truetype');
font-weight: 400;
font-style: normal;
}
#font-face {
font-family: 'Montserrat';
src: url(#/assets/fonts/Montserrat/Montserrat-Regular.ttf) format('truetype');
font-weight: 400;
font-style: normal;
}
The most interesting path is that they actually loaded by the browser.
So inline css looks like this:
#font-face {
font-family: 'Book Antiqua';
src: url("http://localhost:8080/static/media/book_antiqua.d8ae129c.ttf") format("truetype");
font-weight: 400;
font-style: normal; }
#font-face {
font-family: 'Montserrat';
src: url("http://localhost:8080/static/media/Montserrat-Regular.2bb14503.ttf") format("truetype");
font-weight: 400;
font-style: normal; }
But they do not work( So i understand nothing. Browser loaded fonts, font-face syntax looks OK, but they do not trigger.
My webpack config's loaders:
rules: [
{
exclude: [
/\.html$/,
/\.(js|jsx|ts|tsx)$/,
/\.css$/,
/\.json$/,
/\.bmp$/,
/\.gif$/,
/\.jpe?g$/,
/\.png$/,
/\.scss$/,
],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
{
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000',
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]',
},
},
'postcss-loader',
],
}),
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
},
},
'sass-loader',
],
}),
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
loader: 'ts-loader',
},
{
test: /\.(ttf|eot|woff|woff2)$/,
use: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[ext]',
},
},
},
}]
I never import fonts from my assets, I always use services like google fonts to get mine, they have montserrat there and I import it like this
#import url('https://fonts.googleapis.com/css?family=Montserrat');
But that's just a band-aid, another place were a problem could be found is where do you use that font, how do you add that font to a certain class is important, for example for montserrat you should do it like this
font-family: 'Montserrat', sans-serif;
I suspect this is an issue with webpack, but I cannot seem to get this to work. My only CSS file (main.css) contains the following code:
.numpad > input {
text-align: center;
border: 2px solid blue;
margin: auto;
}
However when I publish the application, the CSS file shows the following:
.numpad {
text-align: center;
border: 2px solid blue;
margin: auto;
}
.numpad > input {
text-align: center;
border: 2px solid blue;
margin: auto;
}
I have searched the entire solution for any sort of duplicate that could be causing the first. It doesn't exist.
My webpack config is as follows:
module.exports = (env) => {
const isDevBuild = !(env && env.prod);
return [{
stats: { modules: false },
entry: { 'main': './ClientApp/boot.tsx' },
resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
publicPath: 'dist/'
},
devtool: 'inline-source-map',
module: {
rules: [
{ test: /\.tsx?$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
{ test: /\.css$/, use: isDevBuild ? ['style-loader', 'css-loader'] : ExtractTextPlugin.extract({ use: 'css-loader?minimize' }) },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' },
{ test: /\.js$/, include: /src/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ['env'] } } }
]
},
plugins: [
new CheckerPlugin(),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
}),
new CleanWebpackPlugin(['dist'])
].concat(isDevBuild ? [
// Plugins that apply in development builds only
new webpack.SourceMapDevToolPlugin({
filename: '[file].map', // Remove this line if you prefer inline source maps
moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
})
] : [
// Plugins that apply in production builds only
new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin('main.css')
])
}];
};
Any ideas for why there is a duplicate being created?
The application builds successfully. But when I load it in the browser, it produces the error 'Unexpected token, expected ;' with a marker at the first { character in the css file. I believed I followed the docs but this error will not go away. Any idea what could be causing this error?
webpack.config.js
module.exports = {
...
module: {
rules: [{
test: /\.jsx?$/,
use: 'eslint-loader',
exclude: /node_modules/,
include: Dir.src
}, {
test: /\.jsx?$/,
use: 'babel-loader',
exclude: /node_modules/
}, {
test: /\.json$/,
use: 'json-loader'
}, {
test: /\.woff2(\?[a-z0-9]+)?$/,
use: [{
loader: 'url-loader',
query: {
limit: 10000,
mimetype: 'application/font-woff2'
}
}]
}, {
test: /\.(eot|gif|jpe?g|mp+|png|svg|tff|wav|woff*)$/,
use: [{
loader: 'file-loader',
query: {
limit: 10000
}
}]
}, {
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: 'file-loader'
}, {
test: /favicon\.ico$/,
use: [{
loader: 'url-loader',
query: {
limit: 1,
name: '[name].[ext]',
}
}]
}, {
test: /\.css$/,
use: ['style-loader', 'css-loader']
}, {
test: /\.s[a,c]ss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
]
},
...
}
index.jsx
import React from 'react';
import './index.css';
...
index.css
div { text-overflow: ellipsis; }
button {
border-radius: 0 !important;
cursor: pointer;
padding: 0.6vh 1.2vw;
}
button, .btn, .form-control { border-width: 0.1vh 0.05vw; }
button, .btn, .btn > *, [class^='btn-'], [class^='btn'] > * { font-size: 1.8vmin; }
.btn-group-sm > .btn, .btn-sm {
font-size: 77%;
line-height: 1.5;
}
Produces:
+ 1446 hidden modules
webpack: bundle is now VALID.
{ SyntaxError: C:/simproduct/component/index.css: Unexpected token, expected ; (1:4)
> 1 | div { text-overflow: ellipsis; }
| ^
2 | button {
3 | border-radius: 0 !important;
4 | cursor: pointer;
at Parser.pp$5.raise (C:\simproduct\node_modules\babylon\lib\index.js:4454:13)
at Parser.pp.unexpected (C:\simproduct\node_modules\babylon\lib\index.js:1761:8)
at Parser.pp.semicolon (C:\simproduct\node_modules\babylon\lib\index.js:1742:38)
at Parser.pp$1.parseExpressionStatement (C:\simproduct\node_modules\babylon\lib\index.js:2236:8)
Try the following configuration for test: /.css$/. Make sure that you have postcss-loader in your configuration.
test: /\.css$/,
use: ['style-loader', {loader: 'css-loader', options: { importLoaders: 1 }},
'postcss-loader'
]
}
You will need to have postcss.config.js file; the same location you have your package.json. Add the following; or change is accordingly
module.exports = {
plugins: {
'postcss-import': {},
'postcss-cssnext': {
browsers: ['last 2 versions', '>5%']
}
}
};
Edit
Try to add the following query to your jsx loaders as follows:
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [{
loader: 'babel-loader',
query: {
presets: ['react', 'es2015','stage-1']
}
}
I'm trying to use custom fonts in a Project website with angular4.
This is my Project structure
This is my webpack.config.js
const isDevBuild = !(env && env.prod);
const sharedConfig = {
stats: { modules: false },
context: __dirname,
resolve: { extensions: [ '.js', '.ts' ] },
output: {
filename: '[name].js',
publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
rules: [
{ test: /\.ts$/, include: /ClientApp/, use: ['awesome-typescript-loader?silent=true', 'angular2-template-loader'] },
{ test: /\.html$/, use: 'html-loader?minimize=false' },
{ test: /\.css$/, use: [ 'to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize' ] },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' },
// Font Definitions
{ test: /\.svg$/, loader: 'url?limit=65000&mimetype=image/svg+xml&name=font/[name].[ext]' },
{ test: /\.woff$/, loader: 'url?limit=65000&mimetype=application/font-woff&name=font/[name].[ext]' },
{ test: /\.woff2$/, loader: 'url?limit=65000&mimetype=application/font-woff2&name=font/[name].[ext]' },
{ test: /\.[ot]tf$/, loader: 'url?limit=65000&mimetype=application/octet-stream&name=font/[name].[ext]' },
{ test: /\.eot$/, loader: 'url?limit=65000&mimetype=application/vnd.ms-fontobject&name=font/[name].[ext]' }
]
},
plugins: [new CheckerPlugin()]
};
This is my css with #font-face
#font-face {
font-family: "FuturaMaxiLight";
src: url('/fonts/FuturaMaxi/Futura-Maxi-Light.eot') format('embedded-opentype'), /*for IE */
url('/fonts/FuturaMaxi/Futura-Maxi-Light.ttf') format('truetype'), /* for CSS3 browsers */
url('/fonts/FuturaMaxi/Futura-Maxi-Light.woff') format('woff');
font-weight: normal;
font-style: normal;
}
#font-face {
font-family: "FuturaMaxiDemi";
src: url('/fonts/FuturaMaxi/Futura-Maxi-Demi.eot') format('embedded-opentype'), /*for IE */
url('/fonts/FuturaMaxi/Futura-Maxi-Demi.ttf') format('truetype'), /* for CSS3 browsers */
url('/fonts/FuturaMaxi/Futura-Maxi-Demi.woff') format('woff');
font-weight: normal;
font-style: normal;
}
#font-face {
font-family: "FuturaMaxiBold";
src: url('/fonts/FuturaMaxi/Futura-Maxi-Bold.eot') format('embedded-opentype'), /*for IE */
url('/fonts/FuturaMaxi/Futura-Maxi-Bold.ttf') format('truetype'), /* for CSS3 browsers */
url('/fonts/FuturaMaxi/Futura-Maxi-Bold.woff') format('woff');
font-weight: normal;
font-style: normal;
}
This is the error when I try like that
If I change the css and try to include a dot before the import.
1 dot gives errors.
2 dots breaks the app.
#font-face {
font-family: "FuturaMaxiBold";
src: url('./fonts/FuturaMaxi/Futura-Maxi-Bold.eot') format('embedded-opentype'), /*for IE */
url('./fonts/FuturaMaxi/Futura-Maxi-Bold.ttf') format('truetype'), /* for CSS3 browsers */
url('./fonts/FuturaMaxi/Futura-Maxi-Bold.woff') format('woff');
font-weight: normal;
font-style: normal;
}
Your loaders are specifying name=font/[name].[ext] and your css is looking at /fonts/FuturaMaxi/[name].[ext].
Try changing the loaders to use name=[path][name].[ext] or name=fonts/FuturaMaxi/[name].[ext]
You need resolve-url-loader to resolve the correct path in your build.
See https://github.com/bholloway/resolve-url-loader
Install resolve-url-loader
npm install --save-dev resolve-url-loader
Modify your Webpack CSS rule:
{
test: /\.css$/,
use: [
'to-string-loader',
isDevBuild ? 'css-loader' : 'css-loader?minimize',
'resolve-url-loader' // Add this
]
}
Use relative paths in your CSS files
#font-face {
font-family: "FuturaMaxiLight";
src: url('../fonts/FuturaMaxi/Futura-Maxi-Light.eot') format('embedded-opentype'), /*for IE */
url('../fonts/FuturaMaxi/Futura-Maxi-Light.ttf') format('truetype'), /* for CSS3 browsers */
url('../fonts/FuturaMaxi/Futura-Maxi-Light.woff') format('woff');
font-weight: normal;
font-style: normal;
}
I'm using webpack to compile my sass files.
I have a font-face that looks like this:
#font-face
font-family: "Alef"
src: url("..\..\public\fonts\Alef\Alef-Webfont\Alef-Bold.eot")
src: url("..\..\public\fonts\Alef\Alef-Webfont\Alef-Bold.eot?#iefix") format("embedded-opentype"), url("..\..\public\fonts\Alef\Alef-Webfont\Alef-Bold.woff") format("woff"), url("..\..\public\fonts\Alef\Alef-Webfont\Alef-Bold.ttf") format("truetype"), url("..\..\public\fonts\Alef\Alef-Webfont\Alef-Bold.svg#alefbold") format("svg")
font-weight: bold
font-style: normal
and this is how the loaders in my webpack config file looks like
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\?[a-z0-9=&.]+)?$/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.sass$/,
exclude: /node_modules/,
loader: 'raw-loader!sass-loader'
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw'
}
but, i'm getting 404 on the ttf and woff, so this font appears only in chrome (doesn't appear in firefox and edge)
thanks!
Solved! I separated the srcs, like that:
#font-face
font-family: "Alef"
src: url("..\..\public\fonts\Alef\Alef-Webfont\Alef-Bold.eot")
src: url("..\..\public\fonts\Alef\Alef-Webfont\Alef-Bold.eot?#iefix") format("embedded-opentype")
src: url("..\..\public\fonts\Alef\Alef-Webfont\Alef-Bold.woff") format("woff")
src: url("..\..\public\fonts\Alef\Alef-Webfont\Alef-Bold.ttf") format("truetype")
src: url("..\..\public\fonts\Alef\Alef-Webfont\Alef-Bold.svg#alefbold") format("svg")
font-weight: bold
font-style: normal