Output a single base css class to specify background-image - css

I am using grunt-spritesmith and it generates a css file such as this:
.icon-admin {
background-image: url(../sprites/spritesheet.png);
background-position: -288px -856px;
width: 37px;
height: 32px;
}
.icon-report {
background-image: url(../sprites/spritesheet.png);
background-position: -256px -888px;
width: 26px;
height: 28px;
}
This works fine. What I want to do is to use a base css class for icons for specifying the background-image (like what Compass does), so the output is like this:
.icon {
background-image: url(../sprites/spritesheet.png);
}
.icon-admin {
background-position: -288px -856px;
width: 32px;
height: 32px;
}
.icon-report {
background-position: -256px -888px;
width: 24px;
height: 24px;
}
I wonder if this is possible?

You need to use the cssTemplate function (example).
A quick (and dirty) implementation would be (based on this):
cssTemplate: function(params) {
var fs = require('fs'),
mustache = require('mustache'),
tmpl = fs.readFileSync(__dirname + '/template/css.template.mustache', 'utf8'),
items = params.items,
options = params.options;
// Fallback class naming function
var classFn = options.cssClass || function defaultCssClass (item) {
return '.icon-' + item.name;
};
// Add class to each of the options
items.forEach(function saveClass (item) {
item['class'] = classFn(item);
});
// Set the default class
options.cssClass = options.cssClass || '.icon';
// Render and return CSS
var css = mustache.render(tmpl, params);
return css;
}
Also, you need this template (placed inside a template directory, based on this):
{{options.cssClass}} {
background-image: url({{{spritesheet.escaped_image}}});
}
{{#items}}
{{class}} {
background-position: {{px.offset_x}} {{px.offset_y}};
width: {{px.width}};
height: {{px.height}};
}
{{/items}}
This should do the trick.

Related

Set the initial height of textarea according to its content

I use a reactive angular form that saves all fields disabled. It turns out that textarea creates a scroll and makes reading difficult for those who are just visualizing.
I already tried with css
textarea:disabled {
height: 100%;
font-size: 13px;
text-align: justify;
resize: none;
}
I would like it to expand according to its content, to behave like a DIV with its due paddings.
Thanks #adrian Brand from your code I made other Implements and I got the expected result
ngAfterContentChecked() {
var vtextarea = this.elRef.nativeElement.querySelectorAll('textarea')
for(let i=0;i<vtextarea.length;i++){
vtextarea[i].style.height = vtextarea[i].scrollHeight + 'px';
}
}
The css for better viewing without the scrollbars
textarea:disabled{
height: 100%;
font-size: 13px;
text-align: justify;
resize: none;
overflow: hidden;
}
You could make a directive called contentHeight and use it like
<textarea contentHeight></textarea>
and in the directive
import { Directive, ElementRef } from '#angular/core';
#Directive({
selector: '[contentHeight]'
})
export class ContentHeightDirective {
constructor(private el: ElementRef) { }
ngOnInit() {
const nativeElement = this.el.nativeElement;
nativeElement.style.height = '1px';
console.log(nativeElement.value)
nativeElement.style.height = nativeElement.scrollHeight + 'px';
}
}
https://stackblitz.com/edit/angular-beamvj
you can follow this :)
var textarea = document.querySelector('textarea');
textarea.addEventListener('keydown', autosize);
function autosize(){
var el = this;
setTimeout(function(){
el.style.cssText = 'height:auto; padding:0';
// for box-sizing other than "content-box" use:
// el.style.cssText = '-moz-box-sizing:content-box';
el.style.cssText = 'height:' + el.scrollHeight + 'px';
},0);
}
textarea{
/* box-sizing: padding-box; */
overflow:hidden;
/* demo only: */
padding:10px;
width:250px;
font-size:14px;
margin:50px auto;
display:block;
border-radius:10px;
border:6px solid #ff0000;
}
<textarea rows='1' placeholder='Auto-Expanding Textarea'></textarea>

postcss - css variable as argument inside postcss-mixins

I have a mixin made with postcss-mixins and I want to use a css variable as argument, but it isn't working.
:root {
--padd: 2rem;
}
#define-mixin position $place, $val {
#if $place == end { right: $(val); }
#if $place == start { left: $(val); }
}
And then I call it:
.foo1 {
#mixin position end, 2rem; /* it works -> right: 2rem; */
}
.foo2 {
#mixin position end, var(--padd); /* doesn't work -> right: var(--padd); - it should output 2rem */
}
How can I manage to be able using css variables with postcss-mixins?

Less CSS variable encapsulation and reusable mixins

Can anyone offer any solutions for combining encapsulation and mixin reuse for Less/CSS? I'm trying to keep my variables encapsulated by namespace, but I haven't figured out how to reuse mixins for it.
Example:
#signup-module {
#button-width: 100px;
#button-height: 30px;
#textfield-width: 300px;
#textfield-height: 20px;
.width( #value, #mod:0 ) {
width: ##value + #mod;
}
.height( #value, #mod:0 ) {
height: ##value + #mod;
}
}
.home-page-signup-module {
#signup-module > .width( button-width, -20px );
#signup-module > .height( button-height, -20px );
#signup-module > .width( textfield-width );
#signup-module > .height( textfield-height );
}
The problem is when I create a new module, the width() and height() mixins are repeated.
#contact-us-module {
#button-width: 50px;
#button-height: 20px;
#textfield-width: 300px;
#textfield-height: 20px;
.width( #value, #mod:0 ) {
width: ##value + #mod;
}
.height( #value, #mod:0 ) {
height: ##value + #mod;
}
}
Is there a way to maintain variable encapsulation and eliminate the mixin repetition? I'd like to write .width() and .height() once, but :extend() doesn't seem to work in this context.
Update: May 15, 2014
seven-phases-max offered a great solution below for reusing mixins, but I think I ran into a variable scope issue and the statement below returned an error. It said, "variable #textfield-width is undefined."
.home-page-signup-module {
.module-a.width(textfield-width, -20px);
}
So I tried adding .module-a which seems to work. I'm not 100% sure if this is correct usage but it does fix the error and return the correct value.
.home-page-signup-module {
.module-a;
.module-a.width(textfield-width, -20px);
}
You can collect shared mixins into another namespace/mixin and expand it in each "module" you need, something like this for example:
.shared-stuff() {
.width(#value, #mod: 0) {
width: ##value + #mod;
}
.height(#value, #mod: 0) {
height: ##value + #mod;
}
}
.module-a {
.shared-stuff();
#button-width: 100px;
#button-height: 30px;
#textfield-width: 300px;
#textfield-height: 20px;
}
.module-b {
.shared-stuff();
#button-width: 200px;
// etc.
}
// usage:
.home-page-signup-module {
.module-a.width(button-width, -20px);
.module-b.width(button-width, +33px);
}

Declare variable conditionally in LESS css

I currently have two Views that are using the same layout. However, they differ from each other in the following aspect:
View Foo:
<div class="MajorSection" id="foo">
</div>
View Bar:
<div class="MajorSection" id="bar">
</div>
And I want to declare #labelWidth differently between these two classes in one .less file so that I don't need to repeat myself with the following code.
.MajorSection {
#labelWidth: 10em;
.editor-label {
width: #labelWidth;
}
input, textarea {
width: (#editorWidth)-(.5em); //border & padding
}
}
In View Foo I want #labelWidth to be 10em, and in Bar I want it to be 20em. Is there anyway to do that?
I think the simplest method to achieve this is to define "depended" styles via parametric mixin, e.g.:
.MajorSection {
#foo& {
.labelStyles(10em);
}
#bar& {
.labelStyles(20em);
}
.labelStyles(#width) {
.editor-label {
width: #width;
}
}
input, textarea {
width: (#editorWidth - .5em); // border & padding
}
}
CSS output:
#foo.MajorSection .editor-label {
width: 10em;
}
#bar.MajorSection .editor-label {
width: 20em;
}
.MajorSection input,
.MajorSection textarea {
width: ...;
}

Rendering a Div Based on Browser Type

I have a div tag that looks as follows:
<div id="loadingDiv" class="loadingDiv"; style="position:absolute; left:400px; top:292px;">
<strong>Retrieving Data - One Moment Please...</strong>
</div>
It seems that Chrome and IE do not render this the same way. In IE, the text is much further to the left than with Chrome. I don't know why this is. So, is there a way I can create a style that is dependent on the browser type? For example, if the browser is IE, I'd like the left value to be maybe 300px, and 400px if Chrome. Or, is there a better way to handle this?
Even if I don't recommend to use browser specific CSS, it is always much better to optimize your CSS to look at least simmilar in all browsers, you can do what you want by using of some javascript combined with CSS.
Here is the code:
<html>
<head>
<title>browser specific css</title>
<style>
.loadingDiv {
position: absolute;
display: none;
font-weight: bold;
}
.loadingDiv.ie {
display: block;
left: 300px;
top: 292px;
background: #00CCFF;
color: #454545;
}
.loadingDiv.chrome {
display: block;
left: 400px;
top: 292px;
background: #FCD209;
color: #E53731;
}
.loadingDiv.firefox {
display: block;
left: 400px;
top: 292px;
background: #D04F16;
color: #FFFFFF;
}
.loadingDiv.default {
display: block;
left: 400px;
top: 292px;
}
</style>
<script>
window.onload = function() {
var check_for_ie = detect_browser("MSIE");
var check_for_chrome = detect_browser("Chrome");
var check_for_firefox = detect_browser("Firefox");
var browser_name = "";
var loading_div = document.getElementById("loadingDiv");
var loading_div_html = loading_div.innerHTML;
if (check_for_ie == true) {
browser_name = "Internet Explorer";
loading_div.className = "loadingDiv ie";
}
else if (check_for_chrome == true) {
browser_name = "Google Chrome";
loading_div.setAttribute("class","loadingDiv chrome");
}
else if (check_for_firefox == true) {
browser_name = "Firefox";
loading_div.setAttribute("class","loadingDiv firefox");
}
else {
browser_name = "Unchecked browser";
loading_div.setAttribute("class","loadingDiv default");
}
loading_div.innerHTML = loading_div_html + "(you are browsing with "+browser_name+")";
}
function detect_browser(look_for) {
var user_agent_string = navigator.userAgent;
var search_for_string = user_agent_string.search(look_for);
if (search_for_string > -1) {
return true;
}
else {
return false;
}
}
</script>
</head>
<body>
<div id="loadingDiv" class="loadingDiv" >
Retrieving Data - One Moment Please...
</div>
</body>
</html>
And here is the working example:
http://simplestudio.rs/yard/browser_specific_css/browser_specific_css.html
EDIT:
If you need to check for some other browsers look at user agent string of that specific browser and find something that is unique in it and makes a difference between that browser and the others and use that like this:
var check_for_opera = detect_browser("Opera");
Detecting browsers by user agent could be tricky so be careful, even upgrade my function if you need...
NOTE, that this is just quick example...

Resources