CSS [ Negate the parent element ] - css

Can I do the following:
.content:not([class="no-touch"]) {
.content-index-container {
.chr-selector {
select {
margin-top: 5px;
}
}
}
}
when the no-touch class in not in the content class, but the other way around.
I know that my CSS won't work because it's wrong, but how can I achieve what I'm trying to do: style the content but ignore the styling if the content it's not within the touch class? (Modernizr appends the class to the HTML if touch devices are detected.)

You could reverse your thinking and modify the no-touch child instead....
select { margin-top: 5px; }
.content.no-touch .content-index-container .chr-selector select {
margin-top: 0;
}
or
select { margin-top: 5px; }
.content.no-touch select { margin-top: 0; }

No, I am afraid not. Javascript is your friend or add extra classes to your markup.

Related

Refer to element element selector from another element [duplicate]

For example if I have the following HTML:
<div class="someDiv"></div>
and this CSS:
.opacity {
filter:alpha(opacity=60);
-moz-opacity:0.6;
-khtml-opacity: 0.6;
opacity: 0.6;
}
.radius {
border-top-left-radius: 15px;
border-top-right-radius: 5px;
-moz-border-radius-topleft: 10px;
-moz-border-radius-topright: 10px;
}
.someDiv {
background: #000; height: 50px; width: 200px;
/*** How can I reference the opacity and radius classes here
so this div has those generic rules applied to it as well ***/
}
Like how in scripting languages you have generic functions that are used often written at the top of the script and every time you need to use that function you simply call the function instead of repeating all the code every time.
No, you cannot reference one rule-set from another.
You can, however, reuse selectors on multiple rule-sets within a stylesheet and use multiple selectors on a single rule-set (by separating them with a comma).
.opacity, .someDiv {
filter:alpha(opacity=60);
-moz-opacity:0.6;
-khtml-opacity: 0.6;
opacity: 0.6;
}
.radius, .someDiv {
border-top-left-radius: 15px;
border-top-right-radius: 5px;
-moz-border-radius-topleft: 10px;
-moz-border-radius-topright: 10px;
}
You can also apply multiple classes to a single HTML element (the class attribute takes a space separated list).
<div class="opacity radius">
Either of those approaches should solve your problem.
It would probably help if you used class names that described why an element should be styled instead of how it should be styled. Leave the how in the stylesheet.
You can't unless you're using some kind of extended CSS such as SASS. However it is very reasonable to apply those two extra classes to .someDiv.
If .someDiv is unique I would also choose to give it an id and referencing it in css using the id.
You can easily do so with SASS pre-processor by using #extend.
someDiv {
#extend .opacity;
#extend .radius;
}
Ohterwise, you could use JavaScript (jQuery) as well:
$('someDiv').addClass('opacity radius')
The easiest is of course to add multiple classes right in the HTML
<div class="opacity radius">
If you're willing and able to employ a little jquery, you can simply do this:
$('.someDiv').css([".radius", ".opacity"]);
If you have a javascript that already processes the page or you can enclose it somewhere in <script> tags. If so, wrap the above in the document ready function:
$(document).ready( function() {
$('.someDiv').css([".radius", ".opacity"]);
}
I recently came across this while updating a wordpress plugin. The them has been changed which used a lot of "!important" directives across the css. I had to use jquery to force my styles because of the genius decision to declare !important on several tags.
Just add the classes to your html
<div class="someDiv radius opacity"></div>
I had this problem yesterday. #Quentin's answer is ok:
No, you cannot reference one rule-set from another.
but I made a javascript function to simulate inheritance in css (like .Net):
var inherit_array;
var inherit;
inherit_array = [];
Array.from(document.styleSheets).forEach(function (styleSheet_i, index) {
Array.from(styleSheet_i.cssRules).forEach(function (cssRule_i, index) {
if (cssRule_i.style != null) {
inherit = cssRule_i.style.getPropertyValue("--inherits").trim();
} else {
inherit = "";
}
if (inherit != "") {
inherit_array.push({ selector: cssRule_i.selectorText, inherit: inherit });
}
});
});
Array.from(document.styleSheets).forEach(function (styleSheet_i, index) {
Array.from(styleSheet_i.cssRules).forEach(function (cssRule_i, index) {
if (cssRule_i.selectorText != null) {
inherit_array.forEach(function (inherit_i, index) {
if (cssRule_i.selectorText.split(", ").includesMember(inherit_i.inherit.split(", ")) == true) {
cssRule_i.selectorText = cssRule_i.selectorText + ", " + inherit_i.selector;
}
});
}
});
});
Array.prototype.includesMember = function (arr2) {
var arr1;
var includes;
arr1 = this;
includes = false;
arr1.forEach(function (arr1_i, index) {
if (arr2.includes(arr1_i) == true) {
includes = true;
}
});
return includes;
}
and equivalent css:
.test {
background-color: yellow;
}
.productBox, .imageBox {
--inherits: .test;
display: inline-block;
}
and equivalent HTML :
<div class="imageBox"></div>
I tested it and worked for me, even if rules are in different css files.
Update: I found a bug in hierarchichal inheritance in this solution, and am solving the bug very soon
.

How should page-specific styling be applied to BEM blocks?

Suppose we have a block element named .button which we want to reuse with different margin values on multiple different pages.
Possible solutions:
//1. Nested styles
.page-1 {
.button { margin: 10px; }
}
.page-2 {
.button { margin: 20px; }
}
//2. Specific modifier for EACH page
.button {
&--pg-1-margin { margin: 10px; }
&--pg-2-margin { margin: 20px; }
}
// 3. Special, page-specific block level element
// which will be COMBINED with an existing block-level
// element (ex: <button class="button page-1-element">...</button>)
.page-1-element { margin: 10px; }
.page-2-element { margin: 20px; }
Which one of these will be considered BEM-friendly way?
Is the first method acceptable / preferred way if there are too many different margins used?
Here's the answer to your question in official docs: https://en.bem.info/methodology/css/#external-geometry-and-positioning

What is right BEM approach to global class inheritance?

I recently started using BEM methodology and I'm confused about class inheritance, or rather - when we talk about BEM - some use cases of modifiers.
Let's look at this example, I have a simple element with few children
.b-content { width: 100%; }
.b-content__image { display: block; }
.b-content__date { font-size: 14px; }
.b-content__title { font-size: 30px; }
.b-content__text { font-size: 16px; }
Now I want to reuse my .b-content block with slightly different styles, so I use modifier .m-compact and now I'm not sure what approach is the right one (in BEM).
Whether I should append modifier class to all elements (which I find more valid according to documentation):
.b-content.m-compact { width: 50%; }
.b-content__image.m-compact { display: none; }
.b-content__date.m-compact { font-size: 12px; }
.b-content__title.m-compact { font-size: 24px; }
.b-content__text.m-compact { font-size: 14px; }
or should I append modifier only to the parent element:
.b-content.m-compact { width: 50%; }
.b-content.m-compact .b-content__image { display: none; }
.b-content.m-compact .b-content__date { font-size: 12px; }
.b-content.m-compact .b-content__title { font-size: 24px; }
.b-content.m-compact .b-content__text { font-size: 14px; }
I find this second method more logical, you know, since I'm writing cascading styles and in real world if I want to write e-mail to 10 people, I would write one and just add more recipients, but on the other hand I realize BEM is practically non-cascading approach.
So what should I use and why?
As you point out in the last lines of your question, when doing BEM you should avoid cascading so, as a corollary to this, you don't have to repeat the modifier where it isn't needed.
For your Modifier I'd write something like this:
.b-content--m-compact {
width: 50%;
}
In your example the Block and the Modifier set only the width, so this is a limited use case. In general it comes handy to use some kind of CSS preprocess to ease the code writing, e.g. in SASS:
.my-block
width: 100%
color: red
&--modifier
#extend .my-block
border: 1px solid red
which will results in:
.my-block, .my-block--modifier {
width: 100%;
color: red;
}
.my-block--modifier {
border: 1px solid red;
}
Modifier in BEM looks like this: .block_modName_modValue
You can add additional class - but it's not BEM. And also modifiers have a name and value.
Block in BEM set namespace
So you set default styles for blocks and all unique(that can be changed) place in css with modifiers. This way your styles don't messed up.
To do this you need:
Place common styles in block styles(.portfolio)
Place unique style(with modifiers) like this.(portfolio_theme_list)
In css you don't need to separate this(preprocessor will be needed).
.portfolio {
/* common styles */
&_theme_list {
/* modifiers style */
}
}
In BEM project-stub(template engine) it would look like this:
If you add modifier to block. Then compile(bemjson) to html.
{
block : 'portfolio',
mods : { theme : 'list' },
}
You will see this code
<div class="portfolio portfolio_theme_list">
</div>
You write elements correctly and understand that they need to be separated(without inheritence).
So now you need just define styles for your block with modifier(portfolio_theme_list).
You have 2 options:
1) If you have 2 different blocks - you need separate common and
unique styles. Unique styles place in styles with modified blocks.
2) If you have only 1 different block & you already have styles on
this blocks. Then you can override and don't separate common
styles(but it can cause pain if you add another modifier/instance)

Less - How to insert an #variable into property (as opposed to the value)

In less.js, I'm able to replace values with variables with no problems.
#gutter: 20px;
margin-left:e(%("-%d"), #gutter);
When trying to replace properties with variables, I get errors. How would I perform the following in Less?
#gutter: 20px;
#direction: left;
e(%("margin-%d"), #direction):e(%("-%d"), #gutter);
Thanks to Alvivi for the solution and research (you get the reward for that). I decided to add the following as the actual answer since this is a real way to set it up instead of looking at .blah() pseudo code..
Here's a real strategy for setting it up:
#gutter: 20px;
#dir: left;
#dirOp: right;
then create mixins to enhance margin and padding like so:
.margin(left, #dist:#gutter) {
margin-left:#dist;
}
.margin(right, #dist:#gutter) {
margin-right:#dist;
}
.padding(left, #dist:#gutter) {
padding-left:#dist;
}
.padding(right, #dist:#gutter) {
padding-right:#dist;
}
.lr(left, #dist: 0) {
left: #dist;
}
.lr(right, #dist: 0) {
right: #dist;
}
.. then you can just
#selector {
.margin(#dir);
}
or
#selector {
.margin(#dirOp, 10px);
}
all together:
#selector {
.margin(#dir);
.margin(#dirOp, 50px);
.padding(#dir, 10px);
.padding(#dirOp);
float:#dir;
text-align:#dirOp;
position:absolute;
.lr(#dir);
}
Easy breezy LTR/RTL with LESS! Woot!
Escaping, as says the documentation, is used to create CSS values (not properties).
There is a discussion with some workarounds here. One would be using parametric mixins. For example:
.g () { /* Common properties */ }
.g (right) { margin-right: e(...) }
.g (left) { margin-left: e(...) }

CSS:Defining Styles for input elements inside a div

I have a div called "divContainer" inside which i have few input elements like textboxes,radio buttons et..
How can i define the style for then in the CSS ? I wanna mention styles for elements inside this purticular div.not for the entire form.
Ex: For textboxes i need width as 150px;
For Radio buttons i need width of 20px;
You can define style rules which only apply to specific elements inside your div with id divContainer like this:
#divContainer input { ... }
#divContainer input[type="radio"] { ... }
#divContainer input[type="text"] { ... }
/* etc */
CSS 3
divContainer input[type="text"] {
width:150px;
}
CSS2
add a class "text" to the text inputs then in your css
.divContainer.text{
width:150px;
}
Like this.
.divContainer input[type="text"] {
width:150px;
}
.divContainer input[type="radio"] {
width:20px;
}
When you say "called" I'm going to assume you mean an ID tag.
To make it cross-brower, I wouldn't suggest using the CSS3 [], although it is an option. This being said, give each of your textboxes a class like "tb" and the radio button "rb".
Then:
#divContainer .tb { width: 150px }
#divContainer .rb { width: 20px }
This assumes you are using the same classes elsewhere, if not, this will suffice:
.tb { width: 150px }
.rb { width: 20px }
As #David mentioned, to access anything within the division itself:
#divContainer [element] { ... }
Where [element] is whatever HTML element you need.

Resources