grunt-uncss creating duplicate selectors - css

I'm using grunt-uncss to cleanup my css selectors in a bootstrap / angularjs project I'm working on. I'm using the urls option because I need uncss to parse css at runtime since it's an angular app. I'm also using the files option because I can't get uncss to work without it. This is causing some duplicates in my css. Here's my configuration:
uncss: {
dist: {
options: {
urls: ['http://127.0.0.1:8282/build/index.html#/dashboard',
'http://127.0.0.1:8282/build/index.html#/servicedesk',
'http://127.0.0.1:8282/build/index.html#/email',
'http://127.0.0.1:8282/build/index.html#/calendar',
'http://127.0.0.1:8282/build/index.html#/customers']
},
files: {
'build/css/raw/tidy.css': ['build/index.html']
}
}
}
index.html has two css files, site.css which contains all my application specific selectors and classes, and bootstrap.css
When uncss runs it duplicate many selectors. For example, in site.css there is exactly one
servicedesk {
display: flex;
width: 100%;
height: 100%;
flex-flow: column nowrap;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
flex: 1;
margin: auto;
padding: 1em;
}
after it runs there are 2. I'm not sure why this happens, but I think it is because it processes twice, once at runtime and once using static files. Not sure how to fix that

Found open issue and work around here after much searching: https://github.com/addyosmani/grunt-uncss/issues/66

Related

Scss module (css modules): importing from other scss files

I'm currently converting my sass styles to use css modules to avoid style conflicts. My understanding is that it generates unique class names, which makes it hard if I want to target another component (e.g. a child component) defined in a different file.
Say I have a component Button, and it imports from a Button.module.scss file:
// Button.js
import styles from "./Button.module.scss";
export const Button () => <button className={styles.button} />;
// Button.module.scss
.button {
// relevant styles.
}
Now I have another component ButtonGroup. Say I want to make the button in the group have margin between them, I would have something like this:
// ButtonGroup.module.scss
.buttonGroup {
display: flex
&[class~=horizontal] {
& > .button:not(:first-child) { // still using the same class name
margin-left: 1rem;
}
}
&[class~=vertical] {
flex-direction: column;
& > .button:not(:first-child) { // still using the same class name
margin-top: 1rem;
}
}
}
Notice I'm still using the .button to target the individual buttons. But this won't work because the child component doesn't actually have .button as its class name since it's a generated unique class name.
I could use something like [class^=Button] but that feels hacky and hard to maintain once you have a lot of components. (Also realized it wouldn't work in production.)
css-modules is not related to SASS or SCSS and has its own set of supported features and keywords. Yes, they can be used together, which I actually do in most my projects. But I avoid having classname dependencies between different files. I'm aware of some features that could be used to share classnames, but avoiding the need for it is probably the best solution. I will in the following section list all potential solutions to your conundrum I can think of; choose what suits you best:
Solution #1: Never sharing classnames, co-locating styles that belong together and operate on the same classnames.
In your case this would mean that you only have one scss file relating to buttons buttons.modules.scss and both Button.js and ButtonGroup.js import it.
Solution #2: exempt shared classnames from the unique generated name mechanism by marking them as :global. This can be done thus:
// button.module.scss
// this will stay a global classname
:global(.button) {
// the button styles
}
// this will be treated as usual, generating a local name
.icon {
// some icon stuff
}
// buttongroup.module.scss
.buttonGroup {
display: flex;
// will be resolved as local classname
&.horizontal {
flex-direction: row;
// will be resolved as global classname
& > :global(.button):not(:first-child) { margin-left: 1rem; }
}
&.vertical {
flex-direction: column;
& > :global(.button):not(:first-child) { margin-top: 1rem; }
}
}
Solution #3: accept anonymous children. You can omit the classname of the children. no one places non-buttons in a button group (might even enforce it in your component code).
// buttongroup.module.scss
.buttonGroup {
display: flex;
&.horizontal {
flex-direction: row;
& > *:not(:first-child) { margin-left: 1rem; }
}
&.vertical {
flex-direction: column;
& > *:not(:first-child) { margin-top: 1rem; }
}
}
Solution #4: Reference content from another file. There seems to be some support for a syntax that can reference/import stuff from other files, but I perused the documentation and a few github issue discussions 'import className from fileName' 'more' 'and more' without getting any clear answer as to how one would import a local classname from another file. There might be something possible either along those lines see here:
#import button from './button.module.scss';
.buttonGroup {
display: flex;
&.horizontal {
flex-direction: row;
& > .button:not(:first-child) { margin-left: 1rem; }
}
&.vertical {
flex-direction: column;
& > .button:not(:first-child) { margin-top: 1rem; }
}
}
...or along those lines see here:
:import("./button.module.scss") {
imported-button: button;
}
.buttonGroup {
display: flex;
&.horizontal {
flex-direction: row;
& > .imported-button:not(:first-child) { margin-left: 1rem; }
}
&.vertical {
flex-direction: column;
& > .imported-button:not(:first-child) { margin-top: 1rem; }
}
}
Solution #5: Have your container component add a class .button-group-item to each child and use it to apply the margins instead of the .button class.

How to make these scoped styles reusable for 3 pages only without affecting other pages in Vue.js

There are global classes for components that we are using all around the project.
<style lang="scss" scoped>
.specialPages {
padding: 0 10px 30px 10px;
}
/deep/ .SelectorLabel {
white-space: nowrap;
align-items: center;
display: flex;
}
.Selector {
width: 350px;
white-space: nowrap;
}
.HitButton {
width: 250px;
}
We are using scoped for not effecting the these global classes and simply customize them in scope of the component if needed. However, currently, there are 3 pages are needing these styles and we don't want to affect the rest pages by making these styles global which is used only in 3 pages. How can we overcome this challenge and make these styles reusable only for these 3 pages?
After seeing your comment about having multiple usage of the classes, I did some research and came up with a simpler way to help you with this. I think you should have the styles in a separate .scss file(as earlier suggested) and just import in App.vue. This way you can easily use the classes in the components you want to use them in. So in App.vue, add the below import of the styles(It could live alongside other style rules you may have in the <style /> block in App.vue. Hope this helps.
// App.vue
<style lang="scss" scoped>
#import "path/to/myStyles.scss";
</style>

why does css displays in style tag in the head of react rendred html when i inspect

my component :
import React from "react";
import "./homepage.styles.scss";
const Hompage = () => {
return (
<div className="homepage">
.......
</div>
);
};
export default Hompage;
Style file:
.homepage {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 80px;
}
.directory-menu {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
when i inspect my code it displays as <style> my css </style> int the head
here is a picture of what displays in chrome devtools:
This is the normal or general or common way that the react /angular apps are bunduled into. Where you get all the css and js put into a single index.html page.
You can't avoid it i assume.
But try with lazy loading components but still i think the css would be appended previously into your page.
The css and js are compiled and appended into a main html file so that the browser doesn't have to make a request and wait until it finishes.
1) This way your page will load fast.
2) A server request would be saved.
3) No blocking css or js.
4) and many more ....
Benefits you get using webpack to do this
Even the css library that you are going to use all are appended into a style tag in your page

Reusing LESS mixin classes within optional components

The use case: an application that splits functionality in "plugins". Something like WordPress (observer pattern). Each plugin can also have its own javascript, CSS.
There's a "core" plugin on which most of the others depend on. It comes with a file that contains LESS mixins. Example:
.flex-container(){
display: -ms-flexbox; // ie 10
display: -webkit-box; // safari 6-
display: -webkit-flexbox; // safari 6+
display: -webkit-flex;
display: flex;
}
If I make use of that within plugins I get a lot of repetitive code:
.traffic-box{
.flex-container(); // all the properties above get added here in the compiled CSS
}
.comment-box{
.flex-container(); // again...
}
Is there some way to get better compiled CSS, but without having to apply the class in the plugin HTML? I'd like to avoid using the mixin-type classes in the HTML to make it easier to change styles in the future. For example, changing that element from flex display to anything else using just CSS.
Essentially I'm asking if I can keep the modular structure and have lesscss produce:
.flex-container, .traffic-box, .comment-box{
display: ...
}
As per Harry's comments we can use extend to do this, the only caveat being you must change flex-container to a class from a mixin.
Example
// This now becomes a class
.flex-container{
display: -ms-flexbox; // ie 10
display: -webkit-box; // safari 6-
display: -webkit-flexbox; // safari 6+
display: -webkit-flex;
display: flex;
}
.traffic-box{
&:extend(.flex-container);
}
.comment-box{
&:extend(.flex-container);
}

Is there a CSS postprocessor to inject browser prefixes in CSS files at build time?

Is there a css postprocessor for the Play Framework 2.3.x that automatically adds browser prefixes to a CSS file's rule set?
For example if I'm using Flexbox and my CSS file has this following:
a {
display: flex
}
After a build I'd like that CSS rule to be transformed to:
a {
display: -webkit-box;
display: -webkit-flex;
display: -moz-box;
display: -ms-flexbox;
display: flex
}
So it'd support all the browser specific prefixes without me having to look them up.
I found a javascript solution called prefix-free but I'd prefer a server side solution (preferable when the css and other assets get compiled together).

Resources