adding .css file to ejs - css

im working on node.js(express) with ejs and im not able to include a .css file to it.i tried the same thing seperately as a html-css duo and it worked fine...how can i include the same in my .ejs file. My app.js goes thus:
var express = require('express');
var app = express();
app.set('views', __dirname + '/views');
app.get('/', function(req, res){
res.render('index.ejs', {
title: 'My Site',
nav: ['Home','About','Contact']
});
});
app.get('/home', function(req, res){
res.render('index.ejs', {
title: 'My Site',
nav: ['Home','About','Contact']
});
});
app.get('/about', function(req, res){
res.render('about.ejs', {
title: 'About',
nav: ['Home','About','Contact']
});
});
app.get('/contact', function(req, res){
res.render('contact.ejs', {
title: 'Contact',
nav: ['Home','About','Contact']
});
});
app.listen(3000);
and the index.ejs file:
<html>
<head>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
<div>
<h1> <%= title %> </h1>
<ul>
<% for (var i=0; i<nav.length;i++) {%>
<li> <%=nav[i]%> </li>
<% } %>
</ul>
</div>
<br>
<h3>Node.js</h3>
<p class='just'>Express is agnostic as to which templating language you use. Templating languages can be a hot topic of debate.Here Iam going to use Jade.</p>
<p class ='just'>Again Express is agnostic to what you use to generate your CSS-you can use vanilla CSS but for this example I'm using Stylus.
</p>
<footer>
Running on node with express and ejs
</footer>
</home>
</html>
style.css file:
<style type="text/css">
body { background-color: #D8D8D8;color: #444;}
h1 {font-weight: bold;text-align: center;}
header { padding: 50px 10px; color: #fff; font-size :15px; text-align:right;}
p { margin-bottom :20px; margin-left: 20px;}
footer {text-decoration: overline; margin-top: 300px}
div { width:100%; background:#99CC00;position:static; top:0;left:0;}
.just
{
text-align: center;
}
a:link {color:#FF0000;} /* unvisited link */
a:visited {color:#0B614B;} /* visited link */
a:hover {color:#B4045F;} /* mouse over link */
a:active {color:#0000FF;}
ul { list-style-type:none; margin:0; padding:0;text-align: right; }
li { display:inline; }
</style>

Your problem is not actually specific to ejs.
2 things to note here
style.css is an external css file. So you dont need style tags inside that file. It should only contain the css.
In your express app, you have to mention the public directory from which you are serving the static files. Like css/js/image
it can be done by
app.use(express.static(__dirname + '/public'));
assuming you put the css files in public folder from in your app root.
now you have to refer to the css files in your tamplate files,
like
<link href="/css/style.css" rel="stylesheet" type="text/css">
Here i assume you have put the css file in css folder inside your public folder.
So folder structure would be
.
./app.js
./public
/css
/style.css

In order to serve up a static CSS file in express app (i.e. use a css style file to style ejs "templates" files in express app). Here are the simple 3 steps that need to happen:
Place your css file called "styles.css" in a folder called "assets" and the assets folder in a folder called "public". Thus the relative path to the css file should be "/public/assets/styles.css"
In the head of each of your ejs files you would simply call the css file (like you do in a regular html file) with a <link href=… /> as shown in the code below. Make sure you copy and paste the code below directly into your ejs file <head> section
<link href= "/public/assets/styles.css" rel="stylesheet" type="text/css" />
In your server.js file, you need to use the app.use() middleware. Note that a middleware is nothing but a term that refers to those operations or code that is run between the request and the response operations. By putting a method in middleware, that method will automatically be called everytime between the request and response methods. To serve up static files (such as a css file) in the app.use() middleware there is already a function/method provided by express called express.static(). Lastly, you also need to specify a request route that the program will respond to and serve up the files from the static folder everytime the middleware is called. Since you will be placing the css files in your public folder. In the server.js file, make sure you have the following code:
// using app.use to serve up static CSS files in public/assets/ folder when /public link is called in ejs files
// app.use("/route", express.static("foldername"));
app.use('/public', express.static('public'));
After following these simple 3 steps, every time you res.render('ejsfile') in your app.get() methods you will automatically see the css styling being called. You can test by accessing your routes in the browser.

You can use this
var fs = require('fs');
var myCss = {
style : fs.readFileSync('./style.css','utf8');
};
app.get('/', function(req, res){
res.render('index.ejs', {
title: 'My Site',
myCss: myCss
});
});
put this on template
<%- myCss.style %>
just build style.css
<style>
body {
background-color: #D8D8D8;
color: #444;
}
</style>
I try this for some custom css. It works for me

As I see you are using EJS with express.js
Firstly, there is a better way to add EJS
app.set("view engine", "ejs");
and for that, your file structure should be like
.
./app.js
./view
/index.ejs
And for adding CSS to your EJS file, you have to use "public" folder (or any other name, name doesn't matter) from which you can serve static file like CSS, JS or images
For accessing that, you can use
app.use(express.static("public")); //better and newer way than first answer
and is your EJS file, you can link your CSS by
<link rel="stylesheet" href="css/style.css">
Here I am assuming that, you put your CSS file in your CSS folder inside public folder
So, your file structure will be like
.
./app.js
./public
/css
/style.css
./view
/index.ejs

I tried a different approach. I created an ejs file for my styles called styles.ejs and added all the css inside the tags like this.
<style>
body {
font-family: Tahoma, Geneva, Verdana, sans-serif;
}
#container {
margin: 0 10%;
padding: 20px;
border: 10px solid #c8102e;
}
</style>
and I have includes this file inside head tag of my index.ejs like this.
<head>
<%- include('./css/styles'); %>
</head>
It worked well for me.

app.use(express.static(__dirname + '/public'));
<link href="/css/style.css" rel="stylesheet" type="text/css">
So folder structure should be:
.
./app.js
./public
/css
/style.css

Related

how to call Sass variable in a Vue file

There is a variables.scss file in a project which defines a variable and assigns it a color like this:$contrast: #edebe4The current use of the $contrast variable is to set other variables within the variables.scss file.
Now there is a specific .vue file that's used to render data to the browser and it contains this line of code in its template:<div style="background-color: #edebe4">
When I change that line to<div style="background-color: $contrast">the desired background color disappears from that element.
Is there a way to get that element to recognize the $contrast variable so that whenever the value of $contrast is changed that change flows through automatically to this element?
You can make scss variables available globally (in each component). Just add this to vue.config.js:
css: {
loaderOptions: {
scss: {
additionalData: `#import "~#/variables.scss";`
}
}
}
More info here
Just import variables.scss into your .vue
...
<style lang="scss">
#import "variables.scss"
</style>
This worked -
in variables.scss file added
.contrast-background {
background-color: $contrast;
}
in .vue file changed element to this
<div class="contrast-background">
Amendment -
Here is the final solution that was implemented, which was made possible by #Finn's post -
Changes to .vue file:
added this
<style lang="scss" scoped>
#import "#/layout/design/variables.scss";
.contrast-background {
background-color: $contrast;
}
</style>
and changed element to this
<div class="contrast-background">
This approach avoids changes to the variables.scss file.

Lottie local animation not displaying on web page

I have a simple html do display an animation i made in After Effects, but i can't display the animation when loading it locally (data.json). But if i upload the animation through LottieFiles and use the link generated in my html file, it works. Can someone please explain me why i am not being able to load the animation through my data.json instead from the generated link ?
Bellow i put the code i have so far:
<head>
<!-- Meta -->
<meta charset="UTF-8">
<title>Bodymovin Demo</title>
<style>
body {
text-align: center;
}
h1 {
margin-top: 2em;
}
#bm {
width: 1000px;
margin: 0 auto;
}
</style>
</head>
<body>
<h1>Test Animation</h1>
<div id="bm"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.5.9/lottie.js"></script>
<script>
var animation = bodymovin.loadAnimation({
container: document.getElementById('bm'),
renderer: 'svg',
loop: true,
autoplay: true,
// this way works, but if i put 'data.json' which is on the same directory of this file it doesn't work
path: 'https://assets7.lottiefiles.com/packages/lf20_kxQ49M.json'
});
</script>
</body>
I also have a link to my 'data.json' file:
https://drive.google.com/file/d/1xsikpLLQY-7FMV1_S5VelmB2_85LD-oi/view?usp=sharing
Most likely you are getting a CORS error.
For security reasons browsers don't seem to allow you to load JSON files stored on your computer, it will work as long as the .json file is hosted online.
So through lottiefiles as you've done, or on your web hosting.

Why is my external CSS link 404 upon load?

I tried almost every combination of relative and absolute paths to the CSS file using JavaScript successfully however Sinatra and ERB are more unique.
In the Sinatra script I have the public and stylesheet directories as conventionally done. In my views directory I have the view page with the external
<link href='/some_dir/some_css_file.css' type="text/css" rel="stylesheet" />
I attempted this many times and perhaps it's some nuanced thing I am missing.
How can I get my ERB view file to load the external CSS link?
Sinatra does not have URL helper methods like Rails. I tried moving the CSS file adjacent to the view file and different combinations of relative and absolute paths to the file, but none of them worked.
This code will show a 404 in the Shotgun server log:
ERB view:
<html>
<head>
<link href='../public/stylesheets/sent' type="text/css" rel="stylesheet" />
<link rel="stylesheet" href="/sent.css" />
</head>
<body>
CSS file:
body {
background-color: lightblue;
color: #333;
font-family: Sans-Serif;
line-height: 18px;
}
h1 {
color: green;
}
p {
color: orange;
}
In the terminal while running Shotgun I get These types of errors:
127.0.0.1 - - [05/Nov/2019:23:24:47 -0800] "GET /sent.css HTTP/1.1" 404 509 0.0543
127.0.0.1 - - [05/Nov/2019:23:24:47 -0800] "GET /public/stylesheets/sent HTTP/1.1" 404 534 0.0617
Sinatra, by default, looks for CSS files in a directory called Public, you don't have to include the folder name "Public" on your link tag.
You can still use subfolders inside of the Public folder.
This should work in this case:
<link href='/stylesheets/sent/sent.css' type='text/css' rel='stylesheet' />
If you still want to change the location of the Public folder you can do it by changing the Sinatra configuration, look for this set :public_folder, Proc.new { File.join(root, "static") }
on the following link:
http://sinatrarb.com/configuration.html
body is not closed in your CSS:
body {
background-color: lightblue;
color: #333;
font-family: Sans-Serif;
line-height: 18px;
}
h1 {
color: green;
}
p {
color: orange;
}
For future users of Sinatra making custom MVC apps:
I fixed this problem by storing the public folder in the root dir. This is a convention in Sinatra MVC to keep CSS/JavaScript/pictures in the public directory at the root of the program.
I had it incorrectly nestled in the application directory. Once I moved it up and into the root directory, my relative path <link rel="stylesheet" href="/stylesheets/sent.css" /> worked.

Why doesn't Font Awesome work in my Shadow DOM?

Font Awesome is not working in my shadow DOM since I have the following in it to prevent styles from leaking in and out:
:host {
all: initial; /* 1st rule so subsequent properties are reset. */
display: block;
contain: content; /* Boom. CSS containment FTW. */
}
I'm able to use other stylesheets by just inlining them within the :host property, but that doesn't work with Font Awesome since it uses relative paths in its stylesheet.
I found this post and tried it with the scoped CSS I implement, but the icons show as squares, as can be seen in my example.
I had the same issue with StencilJS.
After hours of struggle and the answer from #Intervalia I was able to fix it.
The problem is that the browser doesn't load the font files when they are only included in the shadow dom (your custom web component). This means that the fonts also has to be included in the normal html file (aka light DOM) so that the browser can detect and load them in order to make them available in the shadow dom.
In my case I didn't use Font awesome instead it was a custom font but I tried it a second time with font awesome and a clean Stenciljs project. The solution is always the same doesn't matter which custom font you need.
Step 1: Move the font into your project. I created a seperate "assets" folder inside the "src" folder to have access from all the components. In this example I downloaded font awesome for web environment https://fontawesome.com/download. (I wouldn't recommend "npm install" since you have to use it in the index.html too)
Step 2: Prepare your web component (in this case my-component.tsx). You can import multiple css files using the styleUrls property. Just import the fontawesome css from your assets directory.
import { Component, Prop, h } from '#stencil/core';
#Component({
tag: 'my-component',
styleUrls: [
'my-component.css',
'../../assets/fontawesome/css/all.css'
],
shadow: true
})
export class MyComponent {
#Prop() first: string;
render() {
return <div> <i class="fas fa-question-circle"></i> </div>;
}
}
Step 3 prepare the file where you want to use the component (in this case index.html). The important line is the "link" tag. This includes the "font awesome css" again and force the Browser to really download the fonts.
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<title>Stencil Component Starter</title>
<link rel="stylesheet" type="text/css" href="./assets/fontawesome/css/all.css">
</head>
<body>
<my-component first="Stencil" last="'Don't call me a framework' JS"></my-component>
</body>
</html>
I know it feels wrong and looks weird but it is not enough to include font awesome only in the index html or in the web component. It must really be included in both files. That doesn't mean the Browser will load it multiple times - it will only be loaded once.
That means that you can't deliver the font with the web component - as far as i know. This isn't a stenciljs bug this is a general problem of the browsers. Please let me know if you have better solutions.
Just for fun here is a screenshot that shows that the browser doesn't load the fonts when it is only included in one file. http://prntscr.com/p2f9tc
Update 05.10.2019:
If you want to use your font inside your web-component the explanation above is correct and still necessary. But you can also use the slot tag inside the web-component. Than you automatically bypass the font from outside (the html) into the web-component. But notice it only works for the stuff you write between the tags of your web component.
That means you can use <my-component> <i class="your-font"/> </my-component>. In this case you don't have to import the font into the web components.
One thing I have noticed is that if the page does not load the CSS file then the shadowDOM won't load it either.
I really think that the only problem us that if the font is not defined on the page that it will not work in the component since the rest of the CSS seems to properly apply to the shadowDOM elements.
This example shows just the shadowDOM trying to load the CSS and it does not work:
let template = `
<style>
:host {
display: block;
}
</style>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<header>
<h1>DreamLine</h1>
<nav>
<ul>
<li>Tour</li>
<li>Blog</li>
<li>Contact</li>
<li>Error</li>
<li><i class="fa fa-search"></i> Search</li>
</ul>
</nav>
</header>
`;
class MyEl extends HTMLElement {
connectedCallback() {
this.attachShadow({mode: 'open'}).innerHTML = template;
}
}
customElements.define("blog-header", MyEl);
<i class="fa fa-battery-full" style="font-size: 45px;"></i>
<hr/>
<blog-header></blog-header>
<hr/>
And this example shows both the page and the shadowDOM loading it and it works:
let template = `
<style>
:host {
display: block;
}
</style>
<header>
<h1>DreamLine</h1>
<nav>
<ul>
<li>Tour</li>
<li>Blog</li>
<li>Contact</li>
<li>Error</li>
<li><i class="fa fa-search"></i> Search</li>
</ul>
</nav>
</header>
`;
class MyEl extends HTMLElement {
connectedCallback() {
const styles = document.querySelector('link[href*="fontawesome"]');
this.attachShadow({mode: 'open'}).innerHTML = template;
if (styles) {
this.shadowRoot.appendChild(styles.cloneNode());
}
}
}
customElements.define("blog-header", MyEl);
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<i class="fa fa-battery-full" style="font-size: 45px;"></i>
<hr/>
<blog-header></blog-header>
<hr/>
The code I like to use looks for the <link> tag I want in the body and then uses a clone of that tag inside the shadowDOM. This way my component is not out of sync. Yes, this can cause problems if the component was not expecting a change in the CSS but I find it works well for my projects.
If you don't need shadow: true then you can load the all.min.css directly via the index.html or the main application. Even loading the all.min.js file works.
If you need it within the shadow dom, then you need to load the all.min.css in index.html and also load it within shadow root using something like this.
`
componentDidLoad(): void {
this.hostElement.shadowRoot
.getElementById("some_Id")
.insertAdjacentHTML(
"afterbegin",
`<link rel="stylesheet" href="${getAssetPath(
"/fontAssets/fontawesome-free/css/all.min.css"
)}" />`
);
}
`
I wanted to share what I did for loading in Font Awesome icons to my stencil components (shadow enabled)...
After several hours into researching this topic, I think I've discovered a solution that will be the most efficient for my components to be bundled in a agnostic way and free of any additional style sheet includes in the HTML header.
My solution was to use the stencil-inline-svg module and then import the svg file directly from the Font Awesome module like this:
// the reference to the svg can be anything (searchIcon name).
// just make sure to import the correct svg from fontawesome node modules.
import searchIcon from 'fontawesome/svgs/regular/search.svg';
#Component({
tag: 'search-icon',
styleUrl: 'search-icon.scss',
shadow: true,
})
export class SearchIconComponent {
render(){
return (
{/* Not ideal to use innerHTML but this renders the full SVG markup */}
<span class="search-btn" innerHTML={searchIcon}></span>
)
}
}
Now, I can set css rules to modify the color and size of my icon like this
.search-btn {
width: 40px; // Set SVG size at the parent.
svg path {
fill: #fff; // Update svg path color.
}
}
Obviously this requires a little bit of Font Awesome icon knowledge so you know which icons to import.
Shadow Doms's style is scoped. And it does not interfere with outer style
FWIW I created a helper method to create a link for font-awesome at the parent page level. Not sure if this is in violation of any custom-elements/Web Components standards but I'll go ahead and post here in hopes that I'll be corrected :) It works for my use case w/ internal web applications for now though.
export const addFontAwesomeStyles = () => {
injectStylesheet("https://use.fontawesome.com/releases/v5.13.0/css/all.css");
injectStylesheet("https://use.fontawesome.com/releases/v5.13.0/css/v4-shims.css");
}
export const injectStylesheet = (href: string) => {
const links = document.head.querySelectorAll("link");
// Already been injected
for(let l in links)
if(links[l].href == href) return;
const link = document.createElement('link');
link.rel = "stylesheet";
link.href = href;
document.head.appendChild(link)
}
Then in your StencilJS component's construtor you can use it like so:
//...
constructor() {
addFontAwesomeStyles();
}

JavaScript and styles outside HTML head are not working on production server

I have a strange problem related to inline javascript and css. On my localhost (WAMP server 2.2) everything works as it should (inline styles and scripts are used and working properly), but on a production server (shared hostgator server) inline scripts are completely overlooked by browsers. If I simplify and give you an example of what I mean:
<html>
<head>
<!--normal head includes, jquery, styles and other stuff -->
</head>
<body>
<script type="text/javascript">
jQuery(document).ready(function() {
alert("test");
});
</script>
<style type="text/css">
a { color:red; }
</style>
Some link
</body>
</html>
On localhost "Some link" will be colored red and an alert will popup. But on the production server none of that happens.
What kind of settings (I assume this is security related) on the server are making this possible and how can I change it so that inline scripts and styles will be used?
Do it programmatically like this:
$(document).ready(function(){
var head = document.getElementsByTagName('head')[0],
style = document.createElement('style'),
css = 'a { color: red }';
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = css;
}
else {
style.appendChild(document.createTextNode(css));
}
head.appendChild(style);
});
I hope it helps.
PS: good practice: load scripts before body closing tag. Only load css in head tag.

Resources