I'm creating a simple page to start to learn HTML, CSS and java script. I have my HTML file with the following link to my CSS file but for some reason none of CSS loads.
I running this on localhost via node.
html:
<!DOCTYPE html>
<html>
<head>
<link href='./css/styles.css' type='text/css' rel='stylesheet'>
</head>
my server.js file:
var http = require('http');
var fs = require('fs');
const PORT=8080;
fs.readFile('./index.html', function (err, html) {
if (err) throw err;
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(PORT);
});
I also get the error
"Resource interpreted as Stylesheet but transferred with MIME type
text/html: "http://localhost:8080/css/styles.css"."
Do I need to add another content-type for "text/css" into my server.js file?
Document tree:
You can add your scripts externally to your html page like this. It could be located inside of the head tags like your CSS definition.
<script type="text/javascript" src="../Script_folder/server.js"></script>
And be carefull about reaching files in the tree. ../ means one level up and ~/ points to root node. So, I wonder that your routing has a certain point with a single . in your CSS address.
<link href='../css/styles.css' type='text/css' rel='stylesheet'>
with two dots. ../
In href attribute you used only one dot instead of two. Your href should be like
<link href='../css/styles.css' type='text/css' rel='stylesheet'>
Related
I am working on a beginner node js server. I am able to render dynamic html using ejs templates but i cannot link css styling to them
I have set up a public directory to store the assets like images and external css files. i have linked to the static contents to express using
app.use(express.static('/public', __dirname + '/public'));
my public folder has images(.jpg) which are rendered but the css in the public folder cannot be rendered.
file structure :
node_modules
models
views
public > app.css, hero.jpg
server.js
package.json
the express app is as below : server.js
const express = require('express');
const app = express();
const ejs = require('ejs');
app.use('/public', express.static(__dirname + '/public');
app.set("view engine", "ejs");
app.set('views',__dirname+'/views');
app.get('/', (req,res) =>{
res.render('home',{
title: "HomePage",
date : new Date().getFullTYear()
}
app.listen(3000);
the home.ejs file has a head section as :
<head>
<meta charset = "utf-8">
<title> My Website <%= title %> </title>
<link rel="stylesheet" href="/app.css" type="text/stylesheet">
</head>
I expected the app.css to load like the in the home.ejs file. But its not working
Looking at your code, I could guess you are setting the static file folder to be /public.
Try modifing you css link to <link rel="stylesheet" href="/public/app.css" type="text/stylesheet">
or try setting the static file config like this:
app.use('/static', express.static(path.join(__dirname, 'public')))
and then <link rel="stylesheet" href="/static/app.css" type="text/stylesheet">
You should declare your public folder this way
app.use(express.static(__dirname + '/public'));
That means you can serve these files as if these were in the root folder. So you can link your css and images this way
<link rel="stylesheet" href="/app.css" type="text/stylesheet">
// in case of image
<img src="/hero.jpg">
When you declare public folder like this
app.use(express.static('/public', __dirname + '/public'));
you set a virtual path prefix for your files and in that case you have to add public in the url path of each file, like this <link rel="stylesheet" href="/public/app.css" type="text/stylesheet">
To use the absolute path of the directory that you want to serve as a part of public folder:
app.use(express.static(path.join(__dirname, 'public')));
Create public folder under the root folder. Under that folder create css folder if you want. So, structure will be link public/css/style.css
You can access style.css like:
<link rel="stylesheet" href="/css/style.css">
CSS files are not loading and on inspecting element(F12) and going to Networks, my CSS file is not visible.
I have added the middleware
app.use(express.static(path.join(__dirname, '/public')));
and also required path above it.
I have added the middleware, required it and npm installed it too.
My Folder Structure
-app.js
-package.json
-package-lock.json
-node_modules
-public
-stylesheets
-main.css
-views
-index.ejs
-partials
-header.ejs
-footer.ejs
My Header.ejs file has this and my body containing some text.
<link href="/stylesheets/main.css">
My app.js file is
var express = require('express');
var request = require('request');
var ejs = require('ejs');
var path = require('path');
var app = express();
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, '/public')));
and my css file changes the color of backgorund, index.ejs file calls the header and footer respectively
<% include partials/header%>
My css code
body{
background-color: purple;
text-align: center;
}
My chrome console shows no error and still I am not able to upload my CSS.
Thanks in advance for your inputs.
You are using the link tag wrong.
You need to supply rel and type attributes for it to load the css and parse it properly. Check out the documentation of link tag to know more
The problem is with the link tag. You have to specify rel, type and href attributes in your link tag.
<link rel = "stylesheet" type = "text/css" href = "/stylesheets/main.css" />
The mater is that your are requesting stylesheet file given an url who will be completed by navigator with the current root path.
For instance, this is your link below.
<link rel="stylesheet" href = "/stylesheets/main.css" />
This is your NodeJS server code.
app.get("/your/root/path", (req, res)=>{
})
Your href link will correspond to /your/root/path/stylesheets/main.css
I think that it will be your problem.
If so, to correct it, set <base> url for static files or don't let your routes path who return views to be in the form /your/root/path but instead /your-root-path
This is Google Optimize CSS Delivery page. At the bottom google suggests use this code to load CSS file at the end of the page body:
<noscript id="deferred-styles">
<link rel="stylesheet" type="text/css" href="small.css"/>
</noscript>
<script>
var loadDeferredStyles = function() {
var addStylesNode = document.getElementById("deferred-styles");
var replacement = document.createElement("div");
replacement.innerHTML = addStylesNode.textContent;
document.body.appendChild(replacement)
addStylesNode.parentElement.removeChild(addStylesNode);
};
var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
if (raf) raf(function() { window.setTimeout(loadDeferredStyles, 0); });
else window.addEventListener('load', loadDeferredStyles);
</script>
</body>
My questions is why not just use this one line to do the job? Especially we are in HTML5 world.
<link rel="stylesheet" type="text/css" href="small.css"/>
</body>
When a browser is parsing an HTML response, it does so line by line. And when it encounters a <link> element, it stops parsing the HTML and goes to fetch the resource set by the element's href attribute.
What the code is doing is wrapping the CSS in a <noscript> element as a fallback, and instead of blocking the page load, making a request for the CSS after the page has finished loading. It is a way to manually give a <link> element similar behavior to the <script> element's defer attribute.
I'm trying to follow the instructions to https://stackoverflow.com/a/18633827/2063561, but I still can't get my styles.css to load.
From app.js
app.use(express.static(path.join(__dirname, 'public')));
In my .ejs, I have tried both of these lines
<link rel="stylesheet" type="text/css" href="/css/style.css" />
<link rel="stylesheet" type="text/css" href="/public/css/style.css" />
Neither loads the css. I've gone into the developer's console noticed the type is set to 'text/html' instead of 'text/css'.
My path looks like
.
./app.js
./public
/css
/style.css
Use this in your server.js file
app.use(express.static(__dirname + '/public'));
and add css like
<link rel="stylesheet" type="text/css" href="css/style.css" />
dont need / before css like
<link rel="stylesheet" type="text/css" href="/css/style.css" />
1.Create a new folder named 'public' if none exists.
2.Create a new folder named 'css' under the newly created 'public' folder
3.create your css file under the public/css path
4.On your html link css i.e
<link rel="stylesheet" type="text/css" href="/css/style.css">
// note the href uses a slash(/) before and you do not need to include the 'public'
5.On your app.js include :
app.use(express.static('public'));
Boom.It works!!
The custom style sheets that we have are static pages in our local file system. In order for server to serve static files, we have to use,
app.use(express.static("public"));
where,
public is a folder we have to create inside our root directory and it must have other folders like css, images.. etc
The directory structure would look like :
Then in your html file, refer to the style.css as
<link type="text/css" href="css/styles.css" rel="stylesheet">
For NodeJS I would get the file name from the res.url, write the header for the file by getting the extension of the file with path.extname, create a read stream for the file, and pipe the response.
const http = require('http');
const fs = require('fs');
const path = require('path');
const port = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
let filePath = path.join(
__dirname,
"public",
req.url === "/" ? "index.html" : req.url
);
let extName = path.extname(filePath);
let contentType = 'text/html';
switch (extName) {
case '.css':
contentType = 'text/css';
break;
case '.js':
contentType = 'text/javascript';
break;
case '.json':
contentType = 'application/json';
break;
case '.png':
contentType = 'image/png';
break;
case '.jpg':
contentType = 'image/jpg';
break;
}
console.log(`File path: ${filePath}`);
console.log(`Content-Type: ${contentType}`)
res.writeHead(200, {'Content-Type': contentType});
const readStream = fs.createReadStream(filePath);
readStream.pipe(res);
});
server.listen(port, (err) => {
if (err) {
console.log(`Error: ${err}`)
} else {
console.log(`Server listening at port ${port}...`);
}
});
Use in your main .js file:
app.use('/css',express.static(__dirname +'/css'));
use in you main .html file:
<link rel="stylesheet" type="text/css" href="css/style.css" />
The reason you getting an error because you are using a comma instead of a concat + after __dirname.
In your app or server.js file include this line:
app.use(express.static('public'));
In your index.ejs, following line will help you:
<link rel="stylesheet" type="text/css" href="/css/style.css" />
I hope this helps, it did for me!
IMHO answering this question with the use of ExpressJS is to give a superficial answer. I am going to answer the best I can with out the use of any frameworks or modules. The reason this question is often answerd with the use of a framework is becuase it takes away the requirment of understanding 'Hypertext-Transfer-Protocall'.
The first thing that should be pointed out is that this is more a problem surrounding "Hypertext-Transfer-Protocol" than it is Javascript. When request are made the url is sent, aswell as the content-type that is expected.
The second thing to understand is where request come from. Iitialy a person will request a HTML document, but depending on what is written inside the document, the document itsself might make requests of the server, such as: Images, stylesheets and more. This question refers to CSS so we will keep our focus there. In a tag that links a CSS file to an HTML file there are 3 properties. rel="stylesheet" type="text/css" and href="http://localhost/..." for this example we are going to focus on type and href. Type sends a request to the server that lets the server know it is requesting 'text/css', and 'href' is telling it where the request is being made too.
so with that pointed out we now know what information is being sent to the server now we can now seperate css request from html request on our serverside using a bit of javascript.
var http = require('http');
var url = require('url');
var fs = require('fs');
function onRequest(request, response){
if(request.headers.accept.split(',')[0] == 'text/css') {
console.log('TRUE');
fs.readFile('index.css', (err, data)=>{
response.writeHeader(200, {'Content-Type': 'text/css'});
response.write(data);
response.end();
});
}
else {
console.log('FALSE');
fs.readFile('index.html', function(err, data){
response.writeHead(200, {'Content_type': 'text/html'});
response.write(data);
response.end();
});
};
};
http.createServer(onRequest).listen(8888);
console.log('[SERVER] - Started!');
Here is a quick sample of one way I might seperate request. Now remember this is a quick example that would typically be split accross severfiles, some of which would have functions as dependancys to others, but for the sack of 'all in a nutshell' this is the best I could do. I tested it and it worked. Remember that index.css and index.html can be swapped with any html/css files you want.
I have used the following steps to resolve this problem
create new folder (static) and move all js and css file into this folder.
then add app.use('/static', express.static('static'))
add css like <link rel="stylesheet" type="text/css" href="/static/style.css"/>
restart server to view impact after changes.
Use this in your server.js file
app.use(express.static('public'));
without the directory ( __dirname ) and then within your project folder create a new file and name it public then put all your static files inside it
Its simple if you are using express.static(__dirname + 'public') then don't forget to put a forward slash before public that is express.static(__dirname + '/public') or use express.static('public') its also going to work;
and don't change anything in CSS linking.
the order of registering routes is important . register 404 routes after static files.
correct order:
app.use("/admin", admin);
...
app.use(express.static(join(__dirname, "public")));
app.use((req, res) => {
res.status(404);
res.send("404");
});
otherwise everything which is not in routes , like css files etc.. , will become 404 .
The above responses half worked and I'm not why they didn't on my machine but I had to do the following for it work.
Created a directory at the root
/public/js/
Paste this into your server.js file with name matching the name of directory created above. Note adding /public as the first param
app.use('/public',express.static('public'));
Finally in the HTML page to which to import the javascript file into,
<script src="public/js/bundle.js"></script>
Example
-- begin: index.html --
<!doctype html>
<html>
<head>
<title>Index</title>
<script type="text/javascript" src="mootools.js"></script>
</head>
<body>
<iframe src="iframe.html" id="innerFrame">blah</iframe>
</body>
</html>
-- end: index.html --
-- begin: iframe.html --
<!doctype html>
<html>
<head>
<title>iFrame</title>
</head>
<body>
<form>
<input id="inputField" type="text" value="this is text." />
</form>
<script type="text/javascript">
$('inputField').set('value', 'updated text');
</script>
</body>
</html>
-- end: iframe.html --
Currently, $('inputField').set('value', 'updated text'); doesn't work :-\
Yes, assuming the iframe and it's parent window are on the same domain, it is possible to load the Mootools scripts once in the parent, and then programmatically extend the IFrame's window and document, instead of re-loading the script within the iframe. It is not the default behavior, as you've noticed, and probably for good reason - I'm guessing most people will tell you it's more trouble than it's worth.
In fact, the IFrame shortcut element constructor used to do that exact thing, but it was ultimately considered to be too much of a hack and not worth the effort to maintain as part of the framework long-term, so they dropped it - this why the documentation for IFrame is kind of odd ("IFrame Method: constructor, Creates an IFrame HTML Element and extends its window and document with MooTools.", and then right below after the example, "Notes: An IFrame's window and document will not be extended with MooTools methods.").
So, the most straightforward way to have $(..) useable in your iframe is just to have the iframe include the Mootools script. If you're feeling fancy, you could also have your parent window inject the Mootools script into the iframe's HEAD, for example:
index.html
<html>
<head>
<title>Parent</title>
<script type="text/javascript" src="mootools.js"></script>
</head>
<body>
<iframe id="innerFrame"></iframe>
<script type="text/javascript">
var mooFrame = new IFrame("innerFrame", {
src:"iframe.html",
events: {
load: function(){
var mooEl = new Element('script', {
type: 'text/javascript',
src: "mootools.js",
events: {
load: function(){
//passed to mooFrame by the iframe
this.pageReady();
}.bind(this)
}
});
this.contentDocument.head.appendChild(mooEl);
}
}
});
</script>
</body>
</html>
iframe.html
<html>
<head>
<title>Iframe</title>
</head>
<body>
<div id="iframe_element"></div>
<script type="text/javascript">
parent.mooFrame.pageReady = function(){
/* Put your iframe javascript in here */
$('iframe_element').set("text", "Fancy!");
};
</script>
</body>
</html>
Update (July 29th): I was fooling around with this idea again and realized there's a fairly obvious though pretty ham-fisted way to transfer Mootools functionality defined in the parent index.html window to the inner iframe: simply include the entire Mootools source into the parent window (remove the src attribute from the existing script element and add an id), and copy that newly enormous element's text into the new script node that gets injected into the head of the iframe. Inlining the Mootools code in the script element in this fashion gives you access to the contents of the element, which you don't get when the javascript is loaded from an external file via the src attribute.
Of course, this..concept is only relevant if the parent window and iframe are on the same-domain, (same as the code provided above).
The obvious drawback is that the Mootools source isn't cached. I'm not sure if there's a use-case where this method would be more optimal than just including mootools in both parent and iframe. In any event, change the index.html file to this:
<html>
<head>
<title>Parent</title>
<script type="text/javascript" id="mootools_js">
**COPY-PASTE THE CONTENTS OF mootools-core.js HERE**
</script>
</head>
<body>
<iframe id="innerFrame"></iframe>
<script type="text/javascript">
var mooFrame = new IFrame("innerFrame", {
src:"iframe.html",
events: {
load: function(){
var mooEl = new Element('script', {
id: 'mootools_iframe_core',
type: 'text/javascript',
html: $('mootools_js').innerHTML
});
this.contentDocument.head.appendChild(mooEl);
this.pageReady();
}
}
});
</script>
</body>
</html>
My previous answer offered two alternative ways of doing the task in question ("load Mootools in a parent frame and then re-use it in iframes"). The first method didn't "re-use" the Mootools functionality loaded into the parent frame, but was rather an alternative way to load the script in the inner iframe. The second method was just a hacky way of copying over the script by putting the entire mootools core source inline in a script element and then copying that element's content into a script element in the iframe's head (hardly optimal).
This following method does programatically extend the window and document objects of the inner iframe. Again, it is assumed that both the parent page and the iframe are on the same domain.
In my (brief and simple) testing, loading the source in both parent and iframe resulted in 72.1 KB transferred at around 130ms (to finish loading both the parent and iframe pages), while the page that loaded the source and then extended the iframe was 36.8 KB and took around 85ms to load both parent and iframe. (that's with gzip on the server...file size of uncompressed/unminified core source is around 134 kb).
For this method a few trivial additions/edits are made to the mootools core source. Download an uncompressed version of mootools-core-1.3.2.js, and rename it to 'mootools-core-init.js' (or whatever). The following steps assume that you checked all boxes on the core builder page except 'Include Compatibility'.
Add this to the top of the 'mootools-core-init.js' file (above the first self-calling anonymous function):
var initMootoolsCore = function(){
var window = this;
var document = this.document;
Add this to the very bottom of the core js file:
};
initMootoolsCore.call(window);
Do the following find/replace tasks:
1
Find:})();
Replace: }).call(this);
2
Find: if (Browser.Element) Element.prototype = Browser.Element.prototype;
Replace: if (this.Browser.Element) Element.prototype = this.Browser.Element.prototype;
3
Find: var IFrame = new Type
Replace: var IFrame = this.IFrame = new Type
4
Find: var Cookie = new Class
Replace: var Cookie = this.Cookie = new Class
(download | compressed version)
In your parent index.html file, put the following script element in the head
<script type="text/javascript" src="mootools-core-init.js"></script>
Finally, in your iframe.html file, put the following inline script element in the head to extend the iframe's window and document (it must be before any included or inline scripts that need to use Mootools):
<script type="text/javascript">parent.initMootoolsCore.call(window);</script>
No, the iframe.html is an independent page. It does not "inherit" anything from the previous page.