How can I add a stylesheet dynamically with NextJS? - javascript

In my nextJS application, I need to load a stylesheet dynamically based on the user preference received from the database.
So, in my page, I'm adding it in the Head (next/head), as follows:
<Head>
<link rel="stylesheet" href={`/fonts/${type}/stylesheet.css`}></link>
</Head>
However, this is giving me a warning in the console in development mode:
Do not add stylesheets using next/head (see <link rel="stylesheet"> tag with href="/fonts/cal/stylesheet.css"). Use Document instead.
See more info here: https://nextjs.org/docs/messages/no-stylesheets-in-head-component
The stylesheet itself contains the font-face:
#font-face {
font-family: "Cal Sans";
src: url("CalSans-SemiBold.woff2") format("woff2"),
url("CalSans-SemiBold.woff") format("woff");
font-weight: 600;
font-style: normal;
font-display: swap;
}
Since the user's preference is stored in the database, and I receive this value via a query, I don't know how I can add it to the Document.js file.
I'll really appreciate any help on this.

While it might be possible to dynamically import a CSS file in your main app component (and you can check out an example in this guide), I would suggest a different solution.
Include all stylesheets in your application, but make its styles only apply when the html (or body) element has a certain class. Then all you need to do is modify that class based on user preference.
// styles.css
body.themeFoo #container {
// some styles...
}
This is how many implementations of dark mode work, e.g. in tailwind CSS. I believe this is a better pattern to solve your problem.

import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html>
<Head>
<link rel="stylesheet" href="..." />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}

This problem is resolved in the new Nextjs version where they provide support for Font Optimization, as documented here - https://nextjs.org/docs/basic-features/font-optimization
It also supports font self-hosting which was the key to my requirements.

Related

Custom font does not load

So I'm creating a full stack React/Node site, my custom fonts don't load on half my pages so far though, one with loads of content and one with no content.. and then they do work on one with loads of content and one with no content ?!? and I have another front end only page where they did originally worked and then stopped working again
I'm assuming its because I'm on a ubuntu virtual machine on my laptop using 5gb ram, is there anything I can do to make it work? I think I can add more ram eventually but is there another fix?
im using chakra UI as well
font face
import { Global } from "#emotion/react";
const Fonts = () => (
<Global
styles={`
#font-face {
font-family: 'BebasNeue';
src: url(fonts/BebasNeue-Regular.woff) format('woff');
}
#font-face {
font-family: 'Vollkorn';
src: url(fonts/Vollkorn.woff) format('woff');
}
#font-face {
font-family: 'Neoneon';
src: url(fonts/Neoneon.woff) format('woff');
} `}
/>
);
export default Fonts;
My pre loads in html
<link
rel="preload"
as="font"
href="./fonts/BebasNeue-Regular.woff2"
type="font/woff2"
crossorigin="anonymous"
value="valid"
/>
<link
rel="preload"
as="font"
href="./fonts/Neoneon.woff2"
type="font/woff2"
crossorigin="anonymous"
value="valid"
/>
<link
rel="preload"
as="font"
href="./fonts/Vollkorn.woff2"
type="font/woff2"
crossorigin="anonymous"
value="valid"
/>
the error codes
ownloadable font: download failed (font-family: "Neoneon" style:normal weight:400 stretch:100 src index:0): status=2147746065 source: http://localhost:3000/recipe/fonts/Neoneon.woff
The resource at “http://localhost:3000/recipe/fonts/BebasNeue-Regular.woff2” preloaded with link preload was not used within a few seconds. Make sure all attributes of the preload tag are set correctly.
Proxy error: Could not proxy request /recipe/fonts/Vollkorn.woff from localhost:3000 to http://localhost/5000.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED)
This works for me using chakra and nextjs.
create a file styles.css with
#font-face {
font-family: "Font";
src: url('../your/path/Font.woff');
font-weight: normal;
font-style: normal;
}
in your index.js
import '../path/styles.css'
then you can use fontFamily properties or use in your theme
export default extendTheme({
// ...
fonts: {
body: `Font`,
},
})
do you don't need to use link and Global component

How to import internal css conditionally with javascript vuejs?

Currently, I have to import css file conditionally depend on which kind of browser users are using. To not making css file global, I have the following code:
created() {
this.checkIsMobile()
},
methods: {
checkIsMobile(){
var isMobile = new MobileDetect(window.navigator.userAgent);
if (isMobile.mobile()){
$('head').append('<link rel="stylesheet" type="text/css" href="#/assets/css/main-pc.css">');
}else {
$('head').append('<link rel="stylesheet" type="text/css" href="#/assets/css/main-m.css">'); //must be load external css
}
},
It does not work because it's internal css.
I can not import in style tag because there are some link to other images in my css. Importing in style will lead to relative modules were not found
How should I do with without uploading css file to somewhere?
Edit: This question is theoretically the same as what I just did (without jQuery)
Vuejs compiles in a different way, so import or adding internal css file to head does not work. Simply use require:
if (isMobile.mobile()){
require('#/assets/css/mobile.css');
}else {
require('#/assets/css/pc.css');
}
Can you try the following method?
<style scoped>
#import './../file.css';
</style>
Source URL: https://forum.vuejs.org/t/how-to-import-css-files-into-single-file-component/41337
You shouldn't use JQuery. It is slow, big size and everything that you using jquery you can do in Vue.
Second, you shouldn't detect screen size in JS, but in CSS.
https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries

How can I dynamically include stylesheets to apply to Polymer 2 element?

I have a custom Polymer 2 video-player element and I want the ability to pass in a property to each element instance in order to define which stylesheet to apply to it (different theme names are released each year and each set of styles currently exist on the server in their own file which has a predictable naming format). I saw some examples with inline tags, but that seems to only be an acceptable solution for smaller styles (otherwise it gets out of control for me to jam all my styles in there, which there are a lot of). How can I do the theme-ing properly?
Here's what I got so far in two separate HTML files:
Demo File (demo-page.html)
<link rel="import" href="../my-video-player.html">
<my-video-player data="{...}" theme="2016"></my-video-player>
<my-video-player data="{...}" theme="2017"></my-video-player>
Component File (my-video-player.html)
<dom-module id="my-video-player">
<template>
<link type="css" rel="import" href="css/[[theme]]/styles.css">
</template>
<script>
class MyVideoPlayer extends Polymer.Element {
...
}
</script>
</dom-module>
Note: I tried putting the above link tag one level outside of the template tag as well, but that didn't work.
Right now what happens is only one of the two theme stylesheets get applied to both of my components. What I need instead is for the first component to get the 2016.css stylesheet applied to it, while the second gets the 2017.css stylesheet.
To add external stylesheets, you need to create a custom component that contains all the styles you want. Then, you can link the "style" component into the component(s) using the styles like this:
<link rel="import" href="/shared-styles.html">
<dom-module id="sus-app">
<template>
<style include="shared-styles"></style>
<style>
neon-animated-pages {
height: 500px;
}
neon-animatable {
padding-top: 2em;
padding-left: 10em;
padding-right: 10em;
}
Notice that you can still include styles unique to the component that she shared styles are being used with.

How to add fonts into NicEdit?

My website allows user write short stories. I want they can free to format and style text, so I install NicEdit to do that. But NicEdit just has 9 default fonts; how to add more?
This is my editor. It use default code with full panel control.
Very happy, I've added news fonts NicEdit successful. I post answer here, hope it userful for everyone has the same problem.
1.Download font file, save in some folder, in my way is 'css/font'
2.Register in css file: add a css file "CustomFonts.css" has content:
(I use Fugaz One download from Google Font)
#font-face {
font-family: "FugazOne";
src: url('font/FugazOne-Regular.ttf');
src: url('font/FugazOne-Regular.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
You may change path to font file.
3.Link css file in html form, before add nicEdit.js lib:
<link rel="stylesheet" type="text/css" href="css/customFont.css" />
<script type="text/javascript" src="js/nicEdit/nicEdit_dev.js"></script>
4.Open nicEdit.js and find word "nicEditorFontFamilySelect". You will see a fonts list use in nicEdit, add new font here by font-family register in css:
sel : {'arial' : 'Arial',..., 'FugazOne':'FugazOne'},
5.tada... DONE!
P/s: when show content from database, you must sure webpage had load customFont.css.

Javascript function that overrides html line

There is a website that references to a .js file and a .css file to format and add dynamic elements to its pages. The website gives the option to reference my own versions of those .js and .css files that I have hosted in a google code repository, and then will use those instead.
I'm trying to add another css file for mobile browsing. Currently I'm using #media arguments within the current css, but I'd like to have two separate css files.
Is there some code I could add to my .js file that would override the html, such that:
<html>
<head>
<link href="desktop.css" ...
Turns into:
<html>
<head>
<link href="mobile.css" ...
When the JS detects a mobile browswer. Keep in mind the js file is referenced further on in the HTML.
Thanks!
You can use media queries on #import rules:
<link href="master.css" …
#import url(desktop.css) (min-width:800px);
#import url(mobile.css) (max-width:700px);
Pls try this
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)) {
document.write('<link rel="stylesheet" type="text/css" href="mobile.css">');
}
else {
document.write('<link rel="stylesheet" type="text/css" href="desktop.css">');
}
And yes, it's a good practice to use CSS #media queries
Is there some code I could add to my .js file that would override the html?
Sure, you could override the html, but what's the point? It'll be too late, the browser will already have loaded and applied desktop.css.
If you want to maintain two separate css files, what you need to do is remove your static link tag, and apply the correct stylesheet dynamically based on browser detection:
var stylesheet=document.createElement("link");
stylesheet.type="text/css";
stylesheet.rel="stylesheet";
if (// detect mobile browser) {
stylesheet.href=mobile.css;
}
else {
stylesheet.href=desktop.css;
}
document.head.appendChild(stylesheet);

Categories