How to assign a CSS page counter to a variable? - css

I want to use the value generated by counter(pages) in order to do something specific on the last page of a printed web document using an #page rule.
Using counter(pages) is working fine for me in an at-page context:
#page {
#top-right {
content: counter(pages);
}
}
Addressing a specific page also works fine:
#page: nth(69) {
#top-right {
content: normal;
}
}
What I want is to pass the total page count to nth(), like so:
#page: nth(#{counter(pages)}) {
#top-right {
content: normal;
}
}
Without success.
I've tried using a SASS variable:
$pagecount: 69; // this works
$pagecount: '69'; // even this works
$pagecount: #{counter(pages)}; // but this doesn't
$pagecount: counter(pages); // nor does this
...
#page: nth(#{$pagecount}) {...}
...
When I try to use the dynamic value my code always compiles to
#page :nth(counter(pages)) {}
which of course does nothing.
Is it possible to get the total page count into nth()?

As pointed out by 3rdthemagical, an answer to this previous question achieves what I want, not by using counter(pages) but instead by using named pages on an element that is positioned on the last page of the document.

Related

Access body lang in SCSS in Angular 6

I am using #ngx/translate core for lang change.
I want to define sass on the basic of
<body lang="en">
or
<body lang="fr">
by if else condition.
Inside my component sass i want to do something like this
#if( bodylang = en)
/these rules
else
// these rules
How can i achieve this?
As it is SCSS you are able to use CSS attribute selectors for this, for example:
a[target="_blank"] {
background-color: yellow;
}
Which in your case would be:
body[lang="en"] {
// Your code
}
body[lang="fr"] {
// Your code
}
You can also nest them like such:
body {
background-color: orange;
&[lang="en"] {
background-color: blue;
}
}
This selector is more specific than just referring to the body tag itself. This means that it will apply the regular body CSS if none of the matching langcode tags are found. You can find more attribute selectors here: https://www.w3schools.com/css/css_attribute_selectors.asp
If you want to do it in your component SCSS file you have to do something like bellow code:
:host-context([lang="en"]){
// Your code
}
:host-context([lang="fa"]){
// Your code
}
If you are doing it in your styles.scss file you can achieve your goal with following code:
[lang="en"] {
// Your code
}
[lang="fr"] {
// Your code
}
rsangin's answer is the correct one.
If you want to select every language that is not en, you can just use :not([lang="en"])

extend from class name in another file sass

So I'm currently doing some styling, following the BEM standard.
An example of what I'm doing could be this:
.block{
&__element {
}
}
what i would like to do is this:
// file a
.block {
...
}
-
// file b
// add magic to reference the `block`class in file a
&__elelemnt {
...
}
What I'm currently doing:
// file a
.block {
...
}
-
// file b
.block__elelemnt {
...
}
(manually adding the block part to the name)
Is there any way to reference this in a smarter way?
Thanks in advance
You can have this file structure:
block-1/
--block-1.scss
--element-1.scss
--element-2.scss
block-2/
--block-1.scss
--element-1.scss
--element-2.scss
And import elements files info block files.
block.scss:
.block {
color: red;
#import "element-1.scss";
#import "element-2.scss";
}
element-1.scss:
&__element-1 {
color: green;
}
Compiles to:
.block {
color: red;
&__element-1 {
color: green;
}
}
This is perhaps the best you can do.
$namespace: "block";
.#{$namespace}-myClass {
...
}
OUTPUT
.block-myClass {
...
}
You can keep a variable $namespace at the top of your file or in a different file and import it. The advantage of using a variable is you can update it once and all your references will be updated.
SASS is all about DRY.
As in, if you want to modify anything, you should be able to modify it from one single place. If you need anything available across multiple files, consider defining its value in a _vars file and including it everywhere you need it. Also note this has nothing to do with code shortness, but with code maintainability and flexibility.
In fact, even if you do get to write more code (which, in practice, doesn't happen), the advantage of DRY far outweighs it.
Here's how it should be done:
/* _vars.scss: */
$block:block;
/* a.scss: */
#import _vars;
.#{$block} {
...
}
/* b.scss: */
#import _vars;
.#{$block}__element {
...
}
Now, whenever you need to change block value, you can do it from one place: _vars.scss.
But, in practice, most people use the initial technique (nesting):
.block {
...
&__element {
...
}
}
Chances are .block and .block__element are related and, overall, it makes more sense to put them in same file. As your app grows in complexity, you'll find it harder to keep track of your code if you over-complicate it.

CSS paged media :last page selector

I need to know if I can modify content on the last page with the :last selector.
I'm not sure if it exists, I see it being used in other stackoverflow answers like this: Footer on last printed page.
But I can't find it in the documentation and it does not work when I try to use it.
I'm trying to clear the content on the footer of my last page like this:
#page {
#bottom-right {
content: "Please turn over";
}
}
#page :last {
#bottom-right {
content: none;
}
}
It works when I use it with the :firstselector. How can I get the effect for the last page?
I'm using Weasyprint to print PDF files.
This can be achieved using named pages.
Create an element on the last page (or use an existing one that will appear on the last page) and assign it a last-page class.
Example below:
HTML
<div class="last-page"></div> <!-- Or add this class to an existing element that appears on the last page -->
CSS
.last-page {
page: last_page;
page-break-before: always; /* Use if your last page is blank, else omit. */
}
#page {
#bottom-right {
content: "Please turn over";
}
}
#page last_page {
#bottom-right {
content: none;
}
}
Tested with Weasyprint - worked a charm.
Based on the CSS3 Page docs it appears the :last pseudo-class was removed (or never included).
It might be possible to target the last page using the :blank pseudo-class if you can force a page break at the end of your document. This might have unwanted effects on other blank pages though.

Show image instead of url via CSS

I have:
media/about-logo.png
I can do:
a {
content: url(/media/media/about-logo.png);
}
I need:
a {
content: url( attr(href) );
}
which does not work.
I need css to take text inside href and use it as an url, without hardcoding it.
There's no way to accomplish this with pure CSS and HTML. You'll need to use JavaScript. I'm using jQuery here for simplicity.
$("a").each(function () {
$(this).css('content', 'url('+$(this).attr('href')+')');
});
At this point though, you might as well just use .text which would have an equivalent result.
$("a").each(function () {
$(this).text($(this).attr('href'));
});

Is possible to make an important property value from CSS selector a non important one?

Is possible to make an important property value from CSS selector a non important one?
For example: Bootstrap 3 defines .hide class as:
.hide { display: none !important; }
Is possible to remove the important value without modifying the BS3 source code?
Thinking at somethingl iike
.hide { display: none !remove-important; }
Note that I want to keep the same value! I don't want to set block !important to .hide class because that would not be correct...
I already added a new class .hide-non-important and used it where it was needed:
.hide-not-important { display: none; }
...but the question is: is there any alternative to this?
You don't need to edit the original source code. Just create a stylesheet and place it after the Bootstrap stylesheets and add this to it:
.hide { display: block !important; }
Now, having said this, I would be very careful about doing this. You don't know how many elements across your site have applied this class, and you will almost certainly get unanticipated results.
There is obviously a reason that this class has been applied, I would suggest either:
don't do this
add some other class to the element and add styles to that. Adjust your markup (or use js to apply the class if need be) to something like:
<div class="hide custom-hide-reset"></div>
Then add this style to the stylesheet you've created:
.custom-hide-reset { display: none; }
You can overwrite this with:
body .hide { display: none !important; }
.someclass.hide { display: none !important; }
those two examples have higher priority
The stylesheet objecs are accessible from javascript
var sheets = document.styleSheets
Once you have the stylesheet array, you can iterate over the rules
var rules = sheets[i].cssRules || sheets[i].rules // browser dependency
Each rule has a style property, which is mutable in the usual way.
rule.style[cssPropName] = value;
There is a method on the sheet to delete a rule by index, either deleteRule or removeRule, depending on the browser.
Bottom line, you can find the rule and either edit it or delete and re-add it in a modified form.
Reference: http://www.javascriptkit.com/dhtmltutors/externalcss3.shtml#.Ujsin4ZmjAs
Since the question can be splitted in
how can I remove !important from a rule applied to my page but
without changing its value and
without editing the original CSS file
For pure spirit of adventure only, I think it would be possible in the following way:
load the CSS with jQuery;
perform a replacement of its content, by searching .hide { display: none !important; } and replacing it with .hide { display: none; };
apply the new in-memory altered CSS to the page.
Taking for good the solution posted in this answer, it could be modified with something (totally untested, just to get the idea) like:
$.get(myStylesLocation, function(css)
{
var alteredCss = css.replace(".hide { display: none !important; }",".hide { display: none; }");
$('<style type="text/css"></style>')
.html(alteredCss)
.appendTo("head");
});
You can override the current !important value by another one like
.col{ color:red !important; }
.col{ color:green; } // wont work
.col{ color:blue !important; } // will work and set color blue instead of red
DEMO.
Update :
This question is not about JavaScript but as an alternative you can accomplish the task using these technique, remove the rule using JavaScript and then add a new rule again.
function getCSSRule(ruleName, deleteFlag) {
ruleName=ruleName.toLowerCase();
if (document.styleSheets) {
for (var i=0; i<document.styleSheets.length; i++) {
var styleSheet=document.styleSheets[i];
var ii=0;
var cssRule=false;
do {
if (styleSheet.cssRules) {
cssRule = styleSheet.cssRules[ii];
} else {
cssRule = styleSheet.rules[ii];
}
if (cssRule) {
if (cssRule.selectorText.toLowerCase()==ruleName) {
if (deleteFlag=='delete') {
if (styleSheet.cssRules) {
styleSheet.deleteRule(ii);
} else {
styleSheet.removeRule(ii);
}
return true;
} else {
return cssRule;
}
}
}
ii++;
} while (cssRule)
}
}
return false;
}
function killCSSRule(ruleName) {
return getCSSRule(ruleName,'delete');
}
function addCSSRule(ruleName, v) {
if (document.styleSheets) {
if (!getCSSRule(ruleName)) {
if (document.styleSheets[0].addRule) {
document.styleSheets[0].addRule(ruleName, v,0);
} else {
document.styleSheets[0].insertRule(ruleName+'{'+v+'}', 0);
}
}
}
return getCSSRule(ruleName);
}
// Check the rule before deleting
console.log(getCSSRule('.col')); // .col { color:red !important; }
// At first remove the current rule
killCSSRule('.col');
// Now assign nre rule
addCSSRule('.col', 'color: red');
// Check the rule after deleting
console.log(getCSSRule('.col')); // .col { color:red; }
DEMO. ( Source : Totally Pwn CSS with Javascript )

Resources