Overriding class definitions with Less - html

I'm trying to customize a Joomla template, which is based on Bootstrap. Specifically, I'm trying to make a "hardcoded" .span4 have the width of a .span3. Sure, it would be much easier to change the markup, but I think that's what css is for, despite the way most of us use Bootstrap for defining layout and visual appearance. Besides, where would be the fun of learning?
For that, this is what I'm trying in the my_css.less provided with the template:
.row-fluid #top1.span4 {
.row-fluid .span(3);
background:red;
}
Actually, the "background" bit is only to make sure that I'm not getting the selector wrong. So, I get that element with a red background, but the rest of the properties aren't applied. This is what I get instead:
.row-fluid .span4 {
width: 31.623931623932%;
}
Am I doing anything wrong? Is what I'm trying even possible?
Thank you!
* Edit *
This is the template I'm using in my page:
Perty by SmartAddons
The bit I'm trying to customize is the one at the right of the logo, the one holding the language selector and the social icons.
My client's logo is wider than the one in the template example, so it pushes #top1 to the right, and it pushes the following element (the one containing "galleries", "my account" and the search box) below.
Answering #Harry's question about selectors not matching, mine is ".row-fluid #top1.span4" because I only want my modification to apply to the .span4 contained in #top1. The other piece of code I pasted below is what is being applied instead of what I intend. Also, I wanted my customization to take preference over the default css, so my selector tries to be more specific. It doesn't seem to be wrong, because the background of the element becomes red.
#Harry:
Also, are you using any mixins to generate the width?
I'm not experienced in Less and I wasn't able to find the mixin in bootstrap documentation, but according to #freejosh at this post:
In mixins.less there's a mixin called .span(#columns) that's used to calculate the width, depending on #gridColumnWidth and #gridGutterWidth along with the argument.
Actually, that example is the one I'm trying to adapt to my needs.
I hope my edition made things clearer (or at least not more obscure, english is not my native language).
Thank you again!
* Edit 03/09/2014 *
Ok, I think I'm gettin closer. New code:
.row-fluid #top1.span4 {
#grid > .fluid > .span(3);
background:red;
}
Resulting css:
.row-fluid #top1.span4 {
width: * 3 * 2;
background: red;
}
Of course, the browser complains of an invalid property value. But at least that is a step (forward?)

#grid > .fluid > .span(3);
gives me:
.row-fluid #top1.span4 {
width: 23.40425532%;
*width: 23.35106383%;
background: red;
}
and NOT width: * 3 * 2;
Tested with less.php, less v1.4, v1.7.3. Notice that Less v2 do not compile BS2 at all.
Less v2 fails on #grid > .core > .span(#gridColumns); in navbar.less

Related

Max-width if image height is too small [duplicate]

Is there any way to use conditional statements in CSS?
I'd say the closest thing to "IF" in CSS are media queries, such as those you can use for responsive design. With media queries, you're saying things like, "If the screen is between 440px and 660px wide, do this". Read more about media queries here: http://www.w3schools.com/cssref/css3_pr_mediaquery.asp, and here's an example of how they look:
#media screen and (max-width: 300px) {
body {
background-color: lightblue;
}
}
That's pretty much the extent of "IF" within CSS, except to move over to SASS/SCSS (as mentioned above).
I think your best bet is to change your classes / IDs within the scripting language, and then treat each of the class/ID options in your CSS. For instance, in PHP, it might be something like:
<?php
if( A > B ){
echo '<div class="option-a">';
}
else{
echo '<div class="option-b">';
}
?>
Then your CSS can be like
.option-a {
background-color:red;
}
.option-b {
background-color:blue;
}
No. But can you give an example what you have in mind? What condition do you want to check?
Maybe Sass or Compass are interesting for you.
Quote from Sass:
Sass makes CSS fun again. Sass is CSS, plus nested rules, variables, mixins, and more, all in a concise, readable syntax.
CSS itself doesn't have conditional statements, but here's a hack involving custom properties (a.k.a. "css variables").
In this trivial example, you want to apply a padding based on a certain condition—like an "if" statement.
:root { --is-big: 0; }
.is-big { --is-big: 1; }
.block {
padding: calc(
4rem * var(--is-big) +
1rem * (1 - var(--is-big))
);
}
So any .block that's an .is-big or that's a descendant of one will have a padding of 4rem, while all other blocks will only have 1rem. Now I call this a "trivial" example because it can be done without the hack.
.block {
padding: 1rem;
}
.is-big .block,
.block.is-big {
padding: 4rem;
}
But I will leave its applications to your imagination.
The #supports rule (92% browser support July 2017) rule can be used for conditional logic on css properties:
#supports (display: -webkit-box) {
.for_older_webkit_browser { display: -webkit-box }
}
#supports not (display: -webkit-box) {
.newer_browsers { display: flex }
}
The only conditions available in CSS are selectors and #media. Some browsers support some of the CSS 3 selectors and media queries.
You can modify an element with JavaScript to change if it matches a selector or not (e.g. by adding a new class).
I would argue that you can use if statements in CSS. Although they aren't worded as such. In the example below, I've said that if the check-box is checked I want the background changed to white. If you want to see a working example check out www.armstrongdes.com. I built this for a client. Re size your window so that the mobile navigation takes over and click the nav button. All CSS. I think it's safe to say this concept could be used for many things.
#sidebartoggler:checked + .page-wrap .hamb {
background: #fff;
}
// example set as if statement sudo code.
if (sidebaretoggler is checked == true) {
set the background color of .hamb to white;
}
CSS has become a very powerful tool over the years and it has hacks for a lot of things javaScript can do
There is a hack in CSS for using conditional statements/logic.
It involves using the symbol '~'
Let me further illustrate with an example.
Let's say you want a background to slide into the page when a button is clicked. All you need to do is use a radio checkbox.
Style the label for the radio underneath the button so that when the button is pressed the checkbox is also pressed.
Then you use the code below
.checkbox:checked ~ .background{
opacity:1
width: 100%
}
This code simply states IF the checkbox is CHECKED then open up the background ELSE leave it as it is.
css files do not support conditional statements.
If you want something to look one of two ways, depending on some condition, give it a suitable class using your server side scripting language or javascript. eg
<div class="oh-yes"></div>
<div class="hell-no"></div>
There is no native IF/ELSE for CSS available. CSS preprocessors like SASS (and Compass) can help, but if you’re looking for more feature-specific if/else conditions you should give Modernizr a try. It does feature-detection and then adds classes to the HTML element to indicate which CSS3 & HTML5 features the browser supports and doesn’t support. You can then write very if/else-like CSS right in your CSS without any preprocessing, like this:
.geolocation #someElem {
/* only apply this if the browser supports Geolocation */
}
.no-geolocation #someElem {
/* only apply this if the browser DOES NOT support Geolocation */
}
Keep in mind that you should always progressively enhance, so rather than the above example (which illustrates the point better), you should write something more like this:
#someElem {
/* default styles, suitable for both Geolocation support and lack thereof */
}
.geolocation #someElem {
/* only properties as needed to overwrite the default styling */
}
Note that Modernizr does rely on JavaScript, so if JS is disabled you wouldn’t get anything. Hence the progressive enhancement approach of #someElem first, as a no-js foundation.
Changing your css file to a scss file would allow you to do the trick. An example in Angular would be to use an ngClass and your scss would look like:
.sidebar {
height: 100%;
width: 60px;
&.is-open {
width: 150px
}
}
While this feels like a bit of a hack, and may not work perfectly in all browsers, a method I have used recently combines the fact that CSS (at least in Chrome) seems to ignore invalid values set on properties, and we can set custom properties that fall back to their default value when invalid.
(Note: I haven't deeply tested this, so treat it as a hacky proof of concept/possible idea)
The following is written in SCSS, but it should work just as well in standard CSS:
.hero-image {
// CSS ignores invalid property values
// When this var is set to an image URL, the browser will ignore it
// When this var isn't set, then we will use the default fallback for the var, which is 'none'
display: var(--loading-page-background-image, none);
// This part isn't directly relevant to my 'if' example, but shows how I was actually using this custom property normally
background-image: var(--loading-page-background-image, none);
}
I'm setting the custom property from JavaScript / React, but it would likely work regardless of how you set it:
// 'true' case
const chosenLoaderUrl = "https://www.example.com/loader.png";
// 'false' case
//const chosenLoaderUrl = "";
// containerRef is just a reference to the div object, you could get this with
// jquery or however you need. Since I'm in React, I used useRef() and attached
// that to my div
containerRef.current.style.setProperty(
"--loading-page-background-image",
`url(${chosenLoaderUrl})`
);
When chosenLoaderUrl is set to my url, that url is an invalid value for the display property, so it seems to get ignored.
When chosenLoaderUrl is set to an empty value, it falls back to the default value in my var() statement, so sets display to none
I'm not sure how 'generalisable' this concept it, but figured I would add it to the other suggestions here in case it is useful to anyone.
Your stylesheet should be thought of as a static table of available variables that your html document can call on based on what you need to display. The logic should be in your javascript and html, use javascript to dynamically apply attributes based on conditions if you really need to. Stylesheets are not the place for logic.
You can use combination of jquery and css classes i.e. I want to change a font color of certain element depending on the color of the background:
CSS:
.h3DarkMode{
color: lightgray;
}
.h3LightMode{
color: gray;
}
HTML:
<h3 class="myText">My Text Here...</h3>
JQuery:
var toggleMode = localStorage.getItem("toggleMode");
if (toggleMode == "dark"){
$(".myText").removeClass("h3LightMode").addClass("h3DarkMode");
}else{
$(".myText").removeClass("h3DarkMode").addClass("h3LightMode");
}
No you can't do if in CSS, but you can choose which style sheet you will use
Here is an example :
<!--[if IE 6]>
Special instructions for IE 6 here
<![endif]-->
will use only for IE 6 here is the website where it is from http://www.quirksmode.org/css/condcom.html , only IE has conditional comments. Other browser do not, although there are some properties you can use for Firefox starting with -moz or for safari starting with -webkit. You can use javascript to detect which browser you're using and use javascript if for whatever actions you want to perform but that is a bad idea, since it can be disabled.

How to apply CSS style based on parent element, similar to media queries [duplicate]

I would like to use media queries to resize elements based on the size of a div element they are in. I cannot use the screen size as the div is just used like a widget within the webpage, and its size can vary.
Yes, CSS Container Queries are what you're looking for. The CSS Containment Module is the specification that details this feature.
You can read more about the decade of work, including proposals, proofs-of-concept, discussions and other contributions by the broader web developer community here! For more details on how such a feature might work and be used, check out Miriam Suzanne's extensive explainer.
Currently only Chromium 105+ supports Container queries out of the box, though Safari 16 will include support as well. Hopefully it won't be much longer before we see a robust cross-browser implementation of such a system. It's been a grueling wait, but I'm glad that it's no longer something we simply have to accept as an insurmountable limitation of CSS due to cyclic dependencies or infinite loops or what have you (these are still a potential issue in some aspects of the proposed design, but I have faith that the CSSWG will find a way).
Media queries aren't designed to work based on elements in a page. They are designed to work based on devices or media types (hence why they are called media queries). width, height, and other dimension-based media features all refer to the dimensions of either the viewport or the device's screen in screen-based media. They cannot be used to refer to a certain element on a page.
If you need to apply styles depending on the size of a certain div element on your page, you'll have to use JavaScript to observe changes in the size of that div element instead of media queries.
Alternatively, with more modern layout techniques introduced since the original publication of this answer such as flexbox and standards such as custom properties, you may not need media or element queries after all. Djave provides an example.
I've just created a javascript shim to achieve this goal. Take a look if you want, it's a proof-of-concept, but take care: it's a early version and still needs some work.
https://github.com/marcj/css-element-queries
From a layout perspective, it is possible using modern techniques.
Its made up (I believe) by Heydon Pickering. He details the process here: http://www.heydonworks.com/article/the-flexbox-holy-albatross
Chris Coyier picks it up and works through a demo of it here: https://css-tricks.com/putting-the-flexbox-albatross-to-real-use/
To restate the issue, below we see 3 of the same component, each made up of three orange divs labelled a, b and c.
The second two's blocks display vertically, because they are limited on horizontal room, while the top components 3 blocks are laid out horizontally.
It uses the flex-basis CSS property and CSS Variables to create this effect.
.panel{
display: flex;
flex-wrap: wrap;
border: 1px solid #f00;
$breakpoint: 600px;
--multiplier: calc( #{$breakpoint} - 100%);
.element{
min-width: 33%;
max-width: 100%;
flex-grow: 1;
flex-basis: calc( var(--multiplier) * 999 );
}
}
Demo
Heydon's article is 1000 words explaining it in detail, and I'd highly recommend reading it.
Update 2021/22
As mentioned in other answers, container queries are coming. There is a full spec for it, and its usage is detailed on MDN:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries
and there is a polyfill to get browsers that don't yet support it up to speed:
https://github.com/GoogleChromeLabs/container-query-polyfill
There is a nice little overview video of it here:
https://www.youtube.com/watch?v=gCNMyYr7F6w
This has now shipped to Chrome (05 September 2022)
https://caniuse.com/css-container-queries
A Media Query inside of an iframe can function as an element query. I've successfully implement this. The idea came from a recent post about Responsive Ads by Zurb. No Javascript!
This is currently not possible with CSS alone as #BoltClock wrote in the accepted answer, but you can work around that by using JavaScript.
I created a container query (aka element query) polyfill to solve this kind of issue. It works a bit different than other scripts, so you don’t have to edit the HTML code of your elements. All you have to do is include the script and use it in your CSS like so:
.element:container(width > 99px) {
/* If its container is at least 100px wide */
}
https://github.com/ausi/cq-prolyfill
I ran into the same problem a couple of years ago and funded the development of a plugin to help me in my work. I've released the plugin as open-source so others can benefit from it as well, and you can grab it on Github: https://github.com/eqcss/eqcss
There are a few ways we could apply different responsive styles based on what we can know about an element on the page. Here are a few element queries that the EQCSS plugin will let you write in CSS:
#element 'div' and (condition) {
$this {
/* Do something to the 'div' that meets the condition */
}
.other {
/* Also apply this CSS to .other when 'div' meets this condition */
}
}
So what conditions are supported for responsive styles with EQCSS?
Weight Queries
min-width in px
min-width in %
max-width in px
max-width in %
Height Queries
min-height in px
min-height in %
max-height in px
max-height in %
Count Queries
min-characters
max-characters
min-lines
max-lines
min-children
max-children
Special Selectors
Inside EQCSS element queries you can also use three special selectors that allow you to more specifically apply your styles:
$this (the element(s) matching the query)
$parent (the parent element(s) of the element(s) matching the query)
$root (the root element of the document, <html>)
Element queries allow you to compose your layout out of individually responsive design modules, each with a bit of 'self-awareness' of how they are being displayed on the page.
With EQCSS you can design one widget to look good from 150px wide all the way up to 1000px wide, then you can confidently drop that widget into any sidebar in any page using any template (on any site) and
The question is very vague. As BoltClock says, media queries only know the dimensions of the device. However, you can use media queries in combination with descender selectors to perform adjustments.
.wide_container { width: 50em }
.narrow_container { width: 20em }
.my_element { border: 1px solid }
#media (max-width: 30em) {
.wide_container .my_element {
color: blue;
}
.narrow_container .my_element {
color: red;
}
}
#media (max-width: 50em) {
.wide_container .my_element {
color: orange;
}
.narrow_container .my_element {
color: green;
}
}
The only other solution requires JS.
The only way I can think that you can accomplish what you want purely with css, is to use a fluid container for your widget. If your container's width is a percentage of the screen then you can use media queries to style depending on your container's width, as you will now know for each screen's dimensions what is your container's dimensions. For example, let's say you decide to make your container's 50% of the screen width. Then for a screen width of 1200px you know that your container is 600px
.myContainer {
width: 50%;
}
/* you know know that your container is 600px
* so you style accordingly
*/
#media (max-width: 1200px) {
/* your css for 600px container */
}
You can use the ResizeObserver API. It's still in it's early days so it's not supported by all browsers yet (but there's several polyfills that can help you with that).
This API allows you to attach an event listener when resizing a DOM element.
Demo 1 - Demo 2
I was also thinking of media queries, but then I found this:
http://www.mademyday.de/css-height-equals-width-with-pure-css.html
Maintain the aspect ratio of a div with CSS
Just create a wrapper <div> with a percentage value for padding-bottom, like this:
div {
width: 100%;
padding-bottom: 75%;
background:gold; /** <-- For the demo **/
}
<div></div>
It will result in a <div> with height equal to 75% of the width of its container (a 4:3 aspect ratio).
This technique can also be coupled with media queries and a bit of ad hoc knowledge about page layout for even more finer-grained control.
It's enough for my needs. Which might be enough for your needs too.
For mine I did it by setting the div's max width, hence for small widget won't get affected and the large widget is resized due to the max-width style.
// assuming your widget class is "widget"
.widget {
max-width: 100%;
height: auto;
}

Target CSS to specific eDirectory page

I want to make the major event image on the left height larger, without affecting other pages.
https://islandeguide.com/event/
I Noticed this page has this that makes it unique
h2 class="theme-title" data-trans="Featured Events">Featured Events/h2
So I thought I may be able to do something like
page.themetitle[Featured Events] .col-sm-5 > .theme-box.theme-box-vertical > .theme-box-content img{
height: 350px;
}
I made this part up page.themetitle[Featured Events] so I knew it would not work.
Does anyone know if I can put something there that would work?
Note:
I can add CSS to custom CSS document, but that is all! I do not have access to change the HTML/PHP, also I can not add Javascript.
This website was designed in a way that makes it very difficult to target elements without changing others on different pages, as they share Classes everywhere.
Try this:
h2[data-trans="Featured Events"].theme-title + div.row div.col-sm-5 div.theme-box.theme-box-vertical img {
height: 350px;
}
Edit: You can shorten it a little using the child selector:
h2[data-trans="Featured Events"].theme-title + .row > .col-sm-5 > .theme-box.theme-box-vertical img {
height: 350px;
}

Visual Composer: nth-child not working with css classes

I am working on a website for a client, and she has Visual Composer installed. For a post grid, I need to assign a different color to each post title. My approach was to find the grid-item container and append :nth-child to it, then direct it to the custom css class I really want to apply the different color to.
Example code, based on the actual code:
.vc_grid-item:first-child > ... > vc_gitem-zone-a > ... > .custom-post-title {
background-color: red;
}
.vc_grid-item:nth-child(2) > ... > vc_gitem-zone-a > ... > .custom-post-title {
background-color: green;
}
.vc_grid-item:nth-child(3) > ... > vc_gitem-zone-a > ... > .custom-post-title {
background-color: blue;
}
Strangely enough, this technique worked fine for the hover-text effect over the post's featured image.
I tried nth-of-type, but had little luck with it. It would work, but only parsed the first or second of type, applying the same color to all three divs.
I have tried every path permutation I can think of, but not a single one works.
Trying to track down a path through the endless divs that Visual Composer generates is practically impossible. Using the code inspector (Google Chrome), I found dynamically generated classes, classes injected as inline styles, and classes that were in the rendered HTML, but nowhere to be seen in the inspector. After several hours of carefully mapping out different "class paths" to make this work, I gave up out of sheer frustration.
Interestingly enough, the Visual Composer documentation is clear that, by adding custom css classes through its UI, custom styling is easy and straightforward. My experience is that this is true--if you want to apply the same color to all your divs in the post grid. Try customizing each grid-item independently, though, and it's a whole different ball game...one that may be impossible to win.
Any ideas as to how I might get this to work without resorting to some kind of hacky JavaScript black magic?
If you want to target a series of elements with the class .vc_grid-item, what you need is :nth-of-class... and it doesn't exist.
If you state the type of element, then you can use :nth-of-type:
div:nth-of-type(3).vc_grid-item > ... > .custom-post-title {background-color: blue;}
N.B. This sort of thing will be much easier when CSS4 :nth-match arrives.
Then, in this kind of situation, you will be able to use:
:nth-match(3 of '.vc_grid-item')
Further Reading: http://www.w3.org/TR/selectors4/#selected-child-index
child point to tbody in table
you must use tbody in selector for pointing child to tr
.vc_grid-item tbody :nth-child(1){
background-color: green;
}
.vc_grid-item tbody :nth-child(2){
background-color: blue;
}

Is it wrong to use CSS in this way?

Lately I'm using a CSS structure that makes HTML much cleaner but I don't know if there's something wrong with this.
Instead of using:
.top { //properties }
.top-wrapper { //properties }
.top-logo { //properties }
And for HTML:
<div class="top">
<div class="top-wrapper">
Logo
</div>
</div>
I'm actually coding like this:
.top { //properties }
.top .wrapper { //properties }
.top .wrapper .logo { //properties }
And for HTML:
<div class="top">
<div class="wrapper">
Logo
</div>
</div>
Is it wrong to do this?
It is not wrong, but the more selectors you have, the higher the resulting specifity of your style. For more information about specifity see http://www.w3.org/TR/CSS21/cascade.html#specificity.
Imagine your example
.top .wrapper .logo { font-size: 10px; }
followed by this:
.logo { font-size: 20px; }
The <a class="logo"> will have a font-size of 10px, even though you specified it to be 20px for the second declaration.
It isn't necessarily "wrong" to do this, it works and if you find it easy to use I'd say go for it!
However - there are some drawbacks to this approach, for example your CSS file will end up larger, which will mean longer download times for anybody viewing the website (granted this effect may be negligible)
There's also the issue that, if you want to re-use the styles of top-wrapper on another element, you have to place that element inside a div with a top class, this ends up cluttering your HTML.
(For more information on the above point see OOCSS)
At the end of the day there are benefits and drawbacks to any approach, if you feel really comfortable with this approach, and it is working for you - then stick with it!
EDIT:
It should also be noted that you're second approach will take longer for the browser to render than you're first approach (the browser has to check multiple conditions instead of just one) for more info see this question
Nope.
What your second code is doing is saying, "target all the elements inside elements that have class top, that have the class wrapper and apply such and such properties"
On the other hand, your first code is only targeting the elements that have the class top-wrapper (or whatever) regardless of their parents class.
Depends how you will use that specified class
.logo { //general properties }
.top .wrapper .logo { //specific propery to top wrapper properties that overrides .logo }
.bottom .wrapper .logo { //specific property to bottom wrapper that overrides .logo }
HTML
<div class="top">
<div class="wrapper>
Logo
</div>
</div>
<div class="bottom">
<div class="wrapper>
Logo
</div>
</div>
Generally, it is better
It's not wrong, but it may get verbose and a little slower if you are have 10 levels of nesting. The result may also be harder to debug if both .logo and .wrapper .logo are styled.
On the other hand it may be nice to have a .button looking different in .content or in .menu. In general, use what makes sense in a specific use case.
No right and wrong here: everything depends on the site you are building, if you are in a team and what makes sense to you.
Personally I don't think the html is any cleaner now than it was previously (in this small example) but your CSS specificity has increased and that could have a detrimental knock on effect.
I now ask myself 'why do I want this element styled in this way?'. Sometimes it's because of inheritance, sometimes because it's a specific case that happens to be in a certain area. The example you use seem a good candidate for inheritance, but looking at the rest of the site might lead to a different conclusion.
Adding longer class names doesn't, to my knowledge, greatly decrease performance. I suspect the only effect would be marginal and is unlikely to be noticeable. Really dependant on the implementation
Additionally if you were 'reading' the html it may make more sense to read have class names like top-logo, other wise you need to look for the appropriate ancestor (bearing in mind there may be more than one that could be applicable).
I'm busy moving toward an OOCSS / BEM method (google these for more, so many resources out there...) myself because I believe it will make maintenance easier in the future, plus I find it makes more sense within a team environment. These are approaches that could lead to 'classitis' or otherwise 'messy' html. I don't mind that though and think the larger the site the more sense this makes. If you're making a 4 page site, maybe don't bother.
But this works for me and may not for you. So I go back to my original statement, there's no right or wrong here :)