Have your chrome extension's stylesheets overwrite the site's CSS - css

I am writing a Chrome extension to modify the CSS of a specific page. Although, when I try to apply styles using style.min.css my spreadsheet is rendered before the site's spreadsheet in the cascade. To be precise, my rules are computed before theirs so their rules override mine.
For example, if I try this
article {
background-color: red;
}
their rule gets computed last and my background won't be red.
This is what the dev tools look like. We can see my injected stylesheet doesn't have priority in the cascade.
Also this is my manifest.json without the project description and name.
"content_scripts": [{
"css": ["style.min.css"],
"js": ["main.js"],
"matches": ["https://intra.epitech.eu/*"]
}],
"permissions": ["tabs"]
So if anyone has any idea on how to go around that by prioritising your styles in a chrome extension please leave a comment :)

article {
background-color: red !important;
}
The !important tag stops other styles from overriding your styles.
You should use the !important tag lightly though. Because if you over use it you will start running into conflicting styles when your CSS file becomes very big.

As per the OP comments "run_at": "document_end" works only for js files.
So load js file at document end then insert css files dynamically by loading css files from that js file.
In manifest.json write this
"content_scripts": [
{
"js": ["main.js"],
"matches": ["https://intra.epitech.eu/*"],
"run_at": "document_end"
}
]

More specific rules override more general ones (https://www.w3.org/TR/2011/REC-CSS2-20110607/cascade.html#cascade) :
#homeboard section article {
background-color: red;
}

Related

How to scope Tailwind Css

I cannot find a good way to scope tailwind CSS when including it in a system where I don't want it to apply globally that works with custom build options.
Essentially I want to do this:
.tailwind{
#import "tailwindcss/base";
#import "tailwindcss/components";
#import "tailwindcss/utilities";
}
But PostCSS importer doesn't like this due to the fact it imports before the tailwind placeholders are replaced. So the only way to make it work is to break the build into 2 stages then import the compiled css like:
.tailwind{
#import "tailwindcss.css";
}
It works but it breaks some of the css rules which show up in dev tools.
Is there a better way to scope tailwind to stop it interfering with other systems?
I've found that you can use postcss-nested for this. Install the plugin, add it as the first plugin to your PostCSS config file and this should work:
.tailwind {
#tailwind base;
#tailwind components;
#tailwind utilities;
#tailwind screens;
}
From the docs...
The prefix option allows you to add a custom prefix to all of Tailwind's generated utility classes. This can be really useful when layering Tailwind on top of existing CSS where there might be naming conflicts.
For example, you could add a tw- prefix by setting the prefix option like so:
// tailwind.config.js
module.exports = {
prefix: 'tw-',
}
You will achieve this by setting important in the tailwind config to your parent class or id. See docs.
// tailwind.config.js
module.exports = {
important: '.tailwind',
}
Unfortunately, this seems to only be affecting the components and utilities styles... the base styles will remain unaffected.
As requested leaving my answer here:
I used the prefix as suggested by Lanny
// tailwind.config.js
module.exports = {
prefix: 'tw-',
}
And then made my tailwind css file like this:
#import "tailwindcss/components";
#import "tailwindcss/utilities";
Then I just manually copied any base styles that I wanted manually into my main css file and manually changed anything that conflicted.
I think the tricky part here is actually about the preflight/reset.css. You want to fend off external styling from coming to your scope but also don't want to pollute the external system with your tailwind style.
My current set up include following steps:
In tailwind.config.js we disable the prefight, defining a prefix tw-, and adding an extra selector #app via option important. The last change will add an extra css selector to output, e.g. #app .tw-mb-4.
module.exports = {
important: '#app',
prefix: "tw-",
corePlugins: {
preflight: false,
},
Find and copy the content of base.css from node_modules folder before pasting it into a scss file with a parent selector #app. You can compile this using any online SCSS compiler. This will help you only reset styling within your scope.
#app {
/*content from base.css*/
}
Copy compiled the styling from #2 and paste to the beginning of your tailwind css file.
Structure the html so you contents are wrapped within a div with the id of #app.
Tailwind's important option doesn't seem to add selector to #layer component so you will have to include that in your component styling.
#layer components {
#app .page-h1 {
#apply tw-mt-0 tw-mb-2 tw-text-center tw-leading-8 tw-text-4xl md:tw-text-5xl;
}
}
According to the docs:
If you’d like to completely disable Preflight — perhaps because you’re integrating Tailwind into an existing project or because you’d like to provide your own base styles — all you need to do is set preflight to false in the corePlugins section of your tailwind.config.js file.
This seems to work with Wordpress in the admin but it does remove the normalization, like cursor: pointer on button hover, for example.
What I have done is this
module.exports = {
prefix: 'tw-',
content: [
"./src/**/*.{html,ts}",
],
theme: {
extend: {},
},
purge: {
enabled: true,
content: ['./src/**/*.{html,ts}']
},
plugins: [],
corePlugins: {
preflight: false,
}
}
It will reduce build size as ,I have purged CSS, disable global CSS,as I have used preflight, and now If u want to apply tailwind class use as
<div class="tw-m-4"></div>
As we have used tw in prefix

Using global styles.scss to control :host of every Angular component

I've noticed that every view in my application has a style file starting like this.
:host {
display: flex;
background-color: blue;
}
div.foo {
background-color: red;
}
It seemed as a wise decision to reduce redundancy and move the general definition to styles.scss. Doing so, I noticed that, while the DIV styling continued to work as expected, the effect on the pseudo-selector vanished.
Googling gave me that I can't reach the host element from inside the component but it doesn't say anything about altering it from outside of it (which my global styles.scss certainly is). I also found a blog on Angular view encapsulation where details are discussed in depth, however, without mention of the global styles.scss.
Summarizing, I've found a lot of info on handling :host and a lot of info on applying global styles.scss. However, I've seen rather limited intersection between them. Such an absence of an explicit confirmation implies often that it's infeasible or at least higly discouraged.
Have I misunderstood the point made in the docs? If so, how can I control the :host speudo-class from my global styles.scss? Or is it a special case of no-no and can't be done?
EDIT
A simple solution using CSS only - :host>* { color: blue; } in your root component.
Note: This CSS rule will only design components at the first level, If you want to apply to all components of the app you will need to use the original answer
ORIGINAL
I was looking for an elegant way to get what you are asking for, And the best way I've been able to accomplish this is by using SASS.
I did an experiment and saw when inheriting a SASS file with a :host definition, the :host selector refers to the component that inherits it.
After a try, the steps below works the same with CSS;
the steps (SCSS / CSS tested):
add new folder under src named styling (or whatever you want), add inside new file name _base.scss (note the underscore)
inside _base.scss add the style for :host
in your components sass style, at first line add #import "~src/styling/base";
That's it!
There is a way to define your own import paths for SASS like node_modules libraries, all you need to do is make a stylePreprocessorOptions entry in the options section of the angular.json file. You do not need to include everything using src\sass
angular.json
"options": {
"outputPath": "dist/App",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/sass/styles.scss"
],
"stylePreprocessorOptions": {
"includePaths": [
"src/sass"
]
},
"scripts": []
},
Now in your component styles simply import styles.scss. Don't include the file extension or an initial ~
#import './styles.scss';

Can't access global SASS variables from my component

In my Nuxt app I load all my SASS thus:
css: [
'~assets/scss/main.scss'
],
It works perfectly, except when I'm trying to use some SASS variable from within a component.
<style lang="scss">
.container {
background-color: $white;
}
</style>
In this case I get this error message:
SassError: Undefinied variable: $white
Yet, all of the SCSS contained in the SASS file where the variable is defined works throughout the app.
It is as if the app as a whole knew these files, but each individual component doesn't.
What's going on?
Most of the other answers don't take into account that Nuxt.js hides all the Webpack setup and forces you to do everything through nuxt.config.js.
My guess is that Webpack isn't compiling all the SCSS declarations together and therefore can't find the variable.
It's been a few months since I had this issue so things may have changed but here goes...
Make sure you have the correct Node packages installed (Nuxt DID NOT do this by default for me) npm i -D node-sass sass-loader
Add your CSS & SCSS files to the css: [] section of nuxt.config.js Order matters here so make sure things like variables are added before things that use them if you have separate files.
If you're using layouts (I think that's the default Nuxt setup) make sure that layouts/default.vue has a <style lang="sass"></style> block in it. If I remember correctly this can be empty but had to exist. I only have one layout but it may need to exist in all of them.
If all that seems like too much of a pain, there's a Nuxt Plugin that takes most of the work/management out of that process. Nuxt Style Resources Module
The confusing part is that:
styles from scss files CAN be loaded like this
//nuxt.config.js
css: [
'~assets/scss/main.scss'
],
//global scss file
$varcolor: black
h1{background: $varcolor}
BUT
the variables inside CAN NOT be used inside a component
//inside component
.component {background: $varcolor} // DOES NOT WORK
I also suggest the use of the nuxt style resource module:
https://github.com/nuxt-community/style-resources-module
new founded solution, checked and it's work. Founded here
add #nuxtjs/style-resources
export default {
css: [
'vendor.min.css'
],
modules: [
'#nuxtjs/style-resources'
],
//You will have to add this new object if it doesn't exist already
styleResources: {
scss: ['./assets/scss/main.scss'] // here I use only main scss with globally styles (variables, base etc)
},
}
it's strange, but if u change tilda (~) to dot(.), it's help for someone
from css: [ '~assets/scss/main.scss' ] to css: [ './assets/scss/main.scss' ]
this solution finded here
Us should either load the scss in your component
<style lang="sass">
#import 'path/to/your/_variable.scss'; // Using this should get you the variables
.my-color {
color: $primary-color;
}
Or adding the following to you to your vue.config.js
module.exports = {
css: {
loaderOptions: {
sass: {
data: `#import "#/pathto/variables.scss";`
}
}
}
};
Ref:
SassError: Undefinied variable: $white
Each <style lang="scss"> is compiled individually. You need to #import the file which defines $white into your component before the parser knows what $white means.
This is why most frameworks keep their variables in a _variables.scss file which is imported in all the other SCSS files/contexts.
The _variables.scss is not even loaded in the page, because in most cases it doesn't actually contain any rules. It only contains variable definitions which are imported into other .scss files, which output .css.
Ref:
Yet, all of the SCSS contained in the SASS file where the variable is defined works throughout the app.
If you import an SCSS file in your vue.config.js the output will be an ordinary <style> tag. Its contents will be generated at compile/build time and will result into some CSS (which apply to the entire document).
Unless specifically imported into the component SCSS, (using an #import command), the compiler will not know what $white means.
There is an important distinction to make between compilation context and browser context. Compilation happens at compile time (most likely in node-sass). Browser context is the actual browser, which only understands the CSS resulted from compilation.
How does Vue only apply style rules to the parent and not to the children with the same class? That's achieved by scoping.
It means applying a custom data-v-{key} attribute to all selectors in the generated <style> tag and to all elements the style should apply to.
See this example and inspect it using your web console: https://codesandbox.io/s/vue-template-ge2hb
It produces this markup:
As you can see, the scoped CSS has an extra [data-v-763db97b] added to the selector, which means it only applies to elements having that data attribute.

Losing CSS in content script

I'm using colorbox plugin to create a modal dialog in certain pages. The dialog is created, but I lose all borders / background overlay of my CSS... In the google chrome console I get errors like:
https://www.website.com/br/cgi-bin/images/controls.png [404
not found]
https://www.website.com/br/cgi-bin/images/border.png [404
not found]
While the files 'controls.png' and 'border.png' are in the local directory of the extension/css...
I'm injecting the CSS over content_script of Google Chrome Extension. Manifest:
"content_scripts": [
{
"matches": ["<all_urls>"],
"css": ["colorbox.css"],
"js": ["jquery.min.js", "jquery.colorbox.js", "dominteract.js"],
"run_at": "document_end",
"all_frames": true
}],
I note that in the CSS source code the images are linked this way:
cboxOverlay{background:url(images/overlay.png) repeat 0 0;}
How can I declare this directory to the chrome's extension know this is a local directory and not a remote?
To link your image you have to include your extension's directory, like this:
background:url('chrome-extension://__MSG_##extension_id__/images/overlay.png') repeat 0 0;
You might need to add your image in your manifest as a web_accessible_resource like this:
"web_accessible_resources": [
"images/overlay.png"
]

How to inject a <style> into the head section of a page with a Chrome extension, using a content script

I'm trying to make a very simple extension, that inserts this;
<style>
span.watch-view-count:hover {opacity: 1;}
span.watch-view-count {opacity: 0;}
</style>
right before the body on any YouTube page I visit.
I tried using content script to inject the code above, first I tried putting the code in a CSS file called mycsscode.css and adding it to my manifest.json file like this:
"js": ["script.js"]
but I'm pretty sure nothing happened, since I viewed the source and couldn't find the code anywhere.
Then I tried following the first method in answer to this question but I changed the script.js to script.css hoping it would work, but nope it didn't so I'm stuck.
This are the codes I have so far;
manifest.json file:
{
"name": "Youtube views Hider",
"version": "1.0",
"manifest_version": 2,
"description": "A plain text description",
"permissions": [
"*://youtube.com/*/",
"tabs"],
"content_scripts": [{
"matches": ["*://youtube.com/*/"],
"js": ["myscript.js"]}
]
}
myscript.js:
var s = document.createElement('script');
s.src = chrome.extension.getURL("script.css");
s.onload = function() {
this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);
Note: I'm almost an illiterate when it comes to coding lingo, so please put it in layman's terms.
If you are just inserting/changing CSS, don't even bother with that javascript. Change the manifest to:
{
"name": "Youtube views Hider",
"version": "1.0",
"manifest_version": 2,
"description": "A plain text description",
"content_scripts": [ {
"matches": ["*://*.youtube.com/*"],
"css": ["myCSS.css"]
} ]
}
Where myCSS.css is just:
span.watch-view-count {opacity: 0 !important;}
span.watch-view-count:hover {opacity: 1 !important;}
Note:
Changed the matches value to work on actual YouTube URL's -- Which usually have the form: http://www.youtube.com/watch?...
Note the use of the !important keyword.
If you insist on programmatic injection, see "How to inject CSS using content script file in Chrome extension?".
PS: If all you really want to do is alter a page's look or CSS, the Stylish extension is the fastest easiest way to do that in either Chrome or Firefox.
There are also thousands of pre-made styles available at userstyles.org.
I just read that you say you are a coding layman. Creating an extension is the hard way.
An easier way is to add the Chrome extension called Tampermonkey to achieve page modification.
Here is a nice tutorial to get you started with creating a script for Tampermonkey ( Greasemonkey in Firefox ).
This way to you don't need to worry about the mechanics of running a script on a page.

Resources