nesting css class for sprite image - css

I'm just bit confused on css Id/class nesting.
sample code below:
1) #sprit-img {
display:inline;
border:1px solid #FFF;
text-decoration:none;
display:block;
float:left;
width:50px;
height:50px;
background-image:url(ig-sprite.png);
background-repeat:no-repeat;
margin:5px;
}
2) #sprit-img a.brew{
background-position:2px 0px;}
3) #sprit-img a.scc{
background-position:-295px 2px;}
in page i used like
4) <div id="sprit-img><a class="brew"></a>...</div> `
now i want to use it like
5) <div class="sprit-img"><a class="brew"></a> <span class="scc"></span></div>`
Questions
is it necessary to give anchor or any element tag in code line 2 and 3?
what would be optimal way to get line 5(if Q1 is true, to have in css class i removed # and place . but not working in my page)? is this correct
--
6) .sprit-img{.....same code..}
.brew{...same position..}
.scc{..same postion...}
and use it like in line 5 or
this is correct
7) .sprit-img{.....same code..}
.sprit-img .brew{...same position..} `
Thanks.
edit: I tried some mix put background-image from sprit-img to brew and scc and found that if i put style as in 6 the html part should be like
<div class="anything"><span class="sprit-img brew"></span></div>
and if i put style like in 7 html part should be like
<div class="sprit-img"><span class="sprit-img brew"></span></div>
but could not make it like 5 any idea ...

Q.1: No.
Q.2:
You need a way to target both types of things inside your div at once in order to apply the same bg image, as well as a way to differentiate them. There are numerous solutions.
As long as you're sure that anything nested inside sprit-img should take the background, you could do this:
<div class="sprit-img">
<a class="brew"></a> <span class="scc"></span>
</div>
#sprit-img * { background-image:url(ig-sprite.png) };
#sprit-img .bew { background-position:2px 0px }
#sprit-img .scc { background-position:-295px 2px; }
(note: * is the universal selector)
...though that could get you in trouble if you need any markup inside of those elements (everything would take the background image, and it would be a funky jumble)
So, if you are sure all child elements (nested only 1 level down) should take the background, but nothing inside of those elements should, then you can use the child selector ( > ) like this:
<div class="sprit-img">
<a class="brew"><span> some text></span>some other text</a>
<span class="scc">more text <strong>something important</strong></span><
</div>
#sprit-img > * { background-image:url(ig-sprite.png) };
#sprit-img .bew { background-position:2px 0px }
#sprit-img .scc { background-position:-295px 2px; }
if you want to avoid the universal selector (rendering could be slow on older machines or with earlier browser versions), you could alternatively use (with line 5 markup):
#sprit-img > a, #sprit-img > span { background-image:url(ig-sprite.png) };
#sprit-img .bew { background-position:2px 0px }
#sprit-img .scc { background-position:-295px 2px; }
...which would then only apply to anchors and spans inside of an element with id="sprit-img"
Or you coulld avoid tag-names altogether (if you are super render-speed conscious) (with line 5 markup)
#sprit-img .bew, #sprit-img .scc { background-image:url(ig-sprite.png) };
#sprit-img .bew { background-position:2px 0px }
#sprit-img .scc { background-position:-295px 2px; }
...which illustrates why the answer to your first question is "no"

# is an ID selector, . is a class selector. So you could change to:
.sprit-img {...}
.sprit-img .brew {...}
.sprit-img .scc {...}
and
<div class="sprit-img"><a class="brew"></a> <span class="scc"></span></div>
However, the real problem is your trying to use non-cascading properties in .sprit-img on the child elements. The first selector should be changed to .sprit-img .brew, .sprit-img .scc

Related

How to select specific class prefix while excluding other prefix?

I need to select the body element when it has a class beginning with post-type- but not select it when there's also a class beginning with taxonomy-. Does anyone know how to get this to work?
body[class^="post-type-"],
body[class*=" post-type-"] {
&:not([class^="taxonomy-"]),
&:not([class*=" taxonomy-"]) {
.widefat {
.check-column {
display: none;
}
}
}
}
EDIT: 0stone0's answer below helped me realize the CSS it was outputting was completely wrong, so this new approach is working well:
body[class^="post-type-"]:not([class^="taxonomy-"]):not([class*=" taxonomy-"]),
body[class*=" post-type-"]:not([class^="taxonomy-"]):not([class*=" taxonomy-"]) {
.widefat {
.check-column {
display: none;
}
}
}
div[class*='post-type-']:not([class*="taxonomy-"])
This pure CSS should target the desired element
Select classes that contain post-type-, but not() containing taxonomy-
div[class*='post-type-']:not([class*="taxonomy-"]) {
border: 1px solid red;
}
<div class='post-type-something'>post-type-something</div>
<div class='post-type-something taxonomy-foobar'>post-type-something taxonomy-foobar</div>
<div class='taxonomy-foobar post-type-something'>taxonomy-foobar post-type-something</div>
Note: Demo uses <div> instead of <body> and applies a border when targeted

How to define same css property for multiple classes generated dynamically using ngFor (Angular)?

I am trying to write css for dynamic classes, for that I generated classes using ngFor like below
<div style="max-height: 450px;" *ngFor="let item of data;let i = index" class="card{{i + 1 }}">
.....
</div>
Now I am writing css for above dynamic classes like this ->
#media (min-width: 1399px) {
.card2,
.card6 {
padding-left: 0px;
padding-right: 0px;
}
.card3,
.card7 {
padding-right: 0px;
}
}
#media (min-width: 576px) and (max-width: 768px) {
.card2,
.card4,
.card6 {
padding-left: 0px;
}
}
Now I have less than 8 divs but it can be above 20 and then I will be in trouble.
So Is there any shortest way for defining above css rules like card(n+1){....} ?
If you are using sass or less, you can use control directives, your sass code would look like :
#for $i from 0 through 20 {
.card-#{$i} { padding-left: 0px; }
}
Here is a running example.
Use your current classes as IDs, and use a common class for all.
class="card" id="card-{{ i }}"
If I understood your question correctly, you can see my implementation for inserting classes dynamically here.
Basically you need to create a function that returns your class's name.
If what you need is to create specific CSS styles for every n+1 card element then you can try this:
card:nth-child(n+1){
background-color: red;
}
If there is no pattern and therefore you cannot use sass, then you could look at [ngStyle] directive. Example of using:
<div *ngFor="let item of data;let i = index" class="card-{{i + 1 }}" [ngStyle]="calcStyle(item, i)">
.....
</div>
and return your expected style in your .ts file, like:
calcStyle(item, i){
if (i==6){
return {
'padding-left': '0px;',
'padding-right': '0px;'
}
}
}
But i think, that you should try to avoid setting padding by index of current item. Instead try to use some grid system.
Easy peasy. Just change the value type of your class attribute to accept javascript instead string and add the concatenation.
<div
style="max-height: 450px;"
*ngFor="let item of data;let i = index"
[class]="'card' + (i + 1)">
.....
</div>

Is there a way to style elements based on flex-wrap state?

Quite straight forward, is there a way to know whether an element has been wrapped because of flex-wrap and therefore style it differently?
I would use javascript or jquery to achieve this.
My approach would be:
get the offsetTop of the element using :first-of-type selector.
use the each method of jquery to run through all elements and compare if offsetTop of $(this) is different of the offsetTop value you got on step1.
gotcha
Provide some code if you need help developing it.
You can make the different class with styling that should be applied to that flex-wrap property. You can manage these classes by javascript. Please check the implementation of this approach as:
Here is the code where 2 classes are made, flex-wrap-blue which set flex-wrap to wrap and change color to blue and other class is flex-wrap-green which set flex-wrap to wrap-reverse and change color to green. I am managing these 2 classes by javascript as show the code below:
HTML Code:
<!DOCTYPE html>
<html>
<head></head>
<body>
<button id="btn-wrap">Apply Wrap</button>
<button id="btn-wrap-reverse">Apply Wrap Reverse</button>
<br />
<div class="large-box">
<div class="small-box">One</div>
<div class="small-box">Two</div>
<div class="small-box">Three</div>
<div class="small-box">Four</div>
</div>
</body>
</html>
CSS Code:
.large-box {
display:flex;
width:100px;
border:1px solid #f00;
height:100px;
padding:1% 0 1% 0;
box-sizing:border-box;
}
.small-box {
width:30px;
border:1px solid #f0f;
height:20px;
padding:1%;
}
.flex-wrap-blue {
flex-wrap:wrap;
color:#00f;
}
.flex-wrap-green {
flex-wrap:wrap-reverse;
color:#0f0;
}
Javascript Code:
function addClass(elem, className) {
if (!elem.classList.contains(className)) {
elem.classList.add(className);
}
}
function removeClass(elem, className) {
if (elem.classList.contains(className)) {
elem.classList.remove(className);
}
}
const btnWrap = document.getElementById('btn-wrap');
const btnWrapReverse = document.getElementById('btn-wrap-reverse');
const box = document.getElementsByClassName('large-box')[0];
btnWrap.addEventListener('click', function(){
addClass(box, 'flex-wrap-blue');
removeClass(box, 'flex-wrap-green');
});
btnWrapReverse.addEventListener('click', function(){
addClass(box, 'flex-wrap-green');
removeClass(box, 'flex-wrap-blue');
});
You can find the code working at my Codepen.

Select odd even child excluding the hidden child

Line 3 is a hidden <div> . I don't want that one to be taken from the odd/even css rule.
What is the best approach to get this to work?
.hidden {display:none;}
.box:not(.hidden):nth-child(odd) { background: orange; }
.box:not(.hidden):nth-child(even) { background: green; }
<div class="wrap">
<div class="box">1</div>
<div class="box">2</div>
<div class="box hidden">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
<div class="box">7</div>
</div>
http://jsfiddle.net/k0wzoweh/
Note: There can be multiple hidden elements.
:nth-child() pseudo-class looks through the children tree of the parent to match the valid child (odd, even, etc), therefore when you combine it with :not(.hidden) it won't filter the elements properly.
Alternatively, we could fake the effect by CSS gradient as follows:
.hidden {display:none;}
.wrap {
line-height: 1.2em;
background-color: orange;
background-image: linear-gradient(transparent 50%, green 50%);
background-size: 100% 2.4em;
}
<div class="wrap">
<div class="box">xx</div>
<div class="box">xx</div>
<div class="box hidden">xx</div>
<div class="box">xx</div>
<div class="box">xx</div>
<div class="box">xx</div>
<div class="box">xx</div>
</div>
Pseudo-selectors don't stack, so your :not doesn't affect the :nth-child (nor would it affect :nth-of-type etc.
If you can resort to jQuery, you can use the :visible pseudo-selector there, although that's not a part of the CSS spec.
If you're generating the HTML and can change that, you can apply odd/even with logic at run-time, eg in PHP:
foreach ($divs AS $i => $div) {
echo '<div class="box ' . ($i % 2 ? 'even' : 'odd') . '">x</div>';
}
Even trying to do something tricky like
.box[class='box']:nth-of-type(even)
doesn't work, because the psuedo-selector doesn't even stack onto the attribute selector.
I'm not sure there's any way to do this purely with CSS - I can't think of any right now.
Here's a CSS-only solution:
.box {
background: orange;
}
.box:nth-child(even) {
background: green;
}
.box.hidden {
display: none;
}
.box.hidden ~ .box:nth-child(odd) {
background: green;
}
.box.hidden ~ .box:nth-child(even) {
background: orange;
}
<div class="wrap">
<div class="box">xx</div>
<div class="box">xx</div>
<div class="box hidden">xx</div>
<div class="box">xx</div>
<div class="box">xx</div>
<div class="box">xx</div>
<div class="box">xx</div>
</div>
Since my rows are being hidden with js, I found that the easiest approach for me was to just add an additional hidden row after each real row that I hide, and remove the hidden rows when I show the real rows again.
Hide the rows you want to hide calling .hide() for each table row, then call
$("tr:visible:even").css( "background-color", "" ); // clear attribute for all rows
$("tr:visible:even").css( "background-color", "#ddddff" ); // set attribute for even rows
Add your table name to the selector to be more specific. Using :even makes it skip the Header row.
As #Fateh Khalsa pointed out, I had a similar problem and since I was manipulating my table with JavaScript (jQuery to be precise), I was able to do the following:
(Note: This assumes use of JavaScript/jQuery which the OP did not state whether or not would be available to them. This answer assumes yes, it would be, and that we may want to toggle visibility of hidden rows at some point.)
Inactive records (identified with the CSS class "hideme") are currently visible.
Visitor clicks link to hide inactive records from the list.
jQuery adds "hidden" CSS class to "hideme" records.
jQuery adds additional empty row to the table immediately following the row we just hid, adding CSS classes "hidden" (so it doesn't show) and "skiprowcolor" so we can easily identify these extra rows.
This process is then reversed when the link is clicked again.
Inactive records (identified with the CSS class "hideme") are currently hidden.
Visitor clicks link to show inactive records from the list.
jQuery removes "hidden" CSS class to "hideme" records.
jQuery removes additional empty row to the table immediately following the row we just showed, identified by CSS class "skiprowcolor".
Here's the JavaScript (jQuery) to do this:
// Inactive Row Toggle
$('.toginactive').click(function(e) {
e.preventDefault();
if ($(this).hasClass('on')) {
$(this).removeClass('on'); // Track that we're no longer hiding rows
$('.wrap tr.hideme').removeClass('hidden'); // Remove hidden class from inactive rows
$('.wrap tr.skiprowcolor').remove(); // Remove extra rows added to fix coloring
} else {
$(this).addClass('on'); // Track that we're hiding rows
$('.wrap tr.hideme').addClass('hidden'); // Add hidden class from inactive rows
$('.wrap tr.hideme').after('<tr class="hidden skiprowcolor"></tr>');
// Add extra row after each hidden row to fix coloring
}
});
The HTML link is simple
Hide/Show Hidden Rows
scss for #tim answer's above, to keep class name changes to a minimum
$selector: "box";
$hidden-selector: "hidden";
.#{$selector} {
background: orange;
:nth-child(even) {
background: green;
}
&.#{$hidden-selector} {
display: none;
}
&.#{$hidden-selector} ~ {
.#{$selector} {
&:nth-of-type(odd) {
background: green;
}
&:nth-of-type(even) {
background: orange;
}
}
}
}
Another way, albeit on the fringe side, is to have an extra <tbody> and either move or copy rows there. Or, an extra div wrapper if using OPs example. Copying easiest of course in regards to restoring etc.
This approach can be useful in some cases.
Below is a simple example where rows are moved when filtered. And yes, it is ranking of stripper names, found it fitting as we are talking stripes ... hah
const Filter = {
table: null,
last: {
tt: null,
value: ''
},
name: function (txt) {
let tb_d = Filter.table.querySelector('.data'),
tb_f = Filter.table.querySelector('.filtered'),
tr = tb_d.querySelectorAll('TR'),
f = 0
;
tb_f.innerHTML = '';
if (txt.trim() == '') {
tb_d.classList.remove('hide');
} else {
txt = txt.toLowerCase();
for (let i = 0; i < tr.length; ++i) {
let td = tr[i].querySelectorAll('TD')[1];
if (td.textContent.toLowerCase().includes(txt)) {
tb_f.appendChild(tr[i].cloneNode(true));
f = 1;
}
}
if (f)
tb_d.classList[f ? 'add' : 'remove']('hide');
}
},
key: function (e) {
const v = e.target.value;
if (v == Filter.last.value)
return;
Filter.last.value = v;
clearTimeout(Filter.last.tt);
Filter.last.tt = setTimeout(function () { Filter.name(v); }, 200);
}
};
Filter.table = document.getElementById('table');
Filter.table.addEventListener('keyup', Filter.key);
table {
width: 200px;
border: 3px solid #aaa;
}
tbody tr { background: #e33; }
tbody tr:nth-child(even) { background: #e3e; }
.hide { display: none; }
<table id="table">
<thead>
<tr><th></th><th><input type="text" id="filter" data-keyup="filter" /></th></tr>
<tr><th>#</th><th>Name</th></tr>
</thead>
<tbody class="filtered">
</tbody>
<tbody class="data">
<tr><td>1</td><td>Crystal</td></tr>
<tr><td>2</td><td>Tiffany</td></tr>
<tr><td>3</td><td>Amber</td></tr>
<tr><td>4</td><td>Brandi</td></tr>
<tr><td>5</td><td>Lola</td></tr>
<tr><td>6</td><td>Angel</td></tr>
<tr><td>7</td><td>Ginger</td></tr>
<tr><td>8</td><td>Candy</td></tr>
</tbody>
</table>
You can use another type of CSS selector: tbody > tr:nth-of-type(odd)
to only target tr nodes, and then, instead of using class names to hide the rows, simply wrap them with some element (which hides them), so the CSS selector would only match odd table rows:
const searchElem = document.querySelector('input');
const tableElem = document.querySelector('table');
const tableBody = document.querySelector('tbody');
function search() {
const str = searchElem.value.toLowerCase();
const rows = tableElem.querySelectorAll('tr');
// remove previous wrappers
// https://stackoverflow.com/a/48573634/104380
tableBody.querySelectorAll('div').forEach(w => {
w.replaceWith(...w.childNodes)
});
// create a wrapper which hides its content:
const wrapper = document.createElement("div");
wrapper.setAttribute('hidden', true);
rows.forEach(function(row){
const text = row.textContent.toLowerCase();
if (str.length && !text.includes(str)) {
// replace row with wrapper and put the row inside it
row.replaceWith(wrapper);
wrapper.appendChild(row);
}
});
}
searchElem.addEventListener('keyup', search);
tbody > tr:nth-of-type(odd) {
background: pink
}
<input type="search" placeholder="search">
<table>
<tbody>
<tr><td>Apple<td>220
<tr><td>Watermelon<td>465
<tr><td>Orange<td>94
<tr><td>Pear<td>567
<tr><td>Cherry<td>483
<tr><td>Strawberry<td>246
<tr><td>Nectarine<td>558
<tr><td>Grape<td>535
<tr><td>Mango<td>450
<tr><td>Blueberry<td>911
<tr><td>Pomegranate<td>386
<tr><td>Carambola<td>351
<tr><td>Plum<td>607
<tr><td>Banana<td>292
<tr><td>Raspberry<td>912
<tr><td>Mandarin<td>456
<tr><td>Jackfruit<td>976
<tr><td>Papaya<td>200
<tr><td>Kiwi<td>217
<tr><td>Pineapple<td>710
<tr><td>Lime<td>983
<tr><td>Lemon<td>960
<tr><td>Apricot<td>647
<tr><td>Grapefruit<td>861
<tr><td>Melon<td>226
<tr><td>Coconut<td>868
<tr><td>Avocado<td>385
<tr><td>Peach<td>419
</tbody>
</table>

CSS event on one element, changing an other

How can i change an element with CSS with an event on another element?
E.g. <div id="one"> ....., <div id="two">....
<style>
#one:hover
{
changing the visibility of #two...
}
</style>
In your case, with the element you wish to change being after the element you hover, meaning that you have a structure like:
<div id="one"></div>
<!--you could have some elements between them-->
<div id="two"></div>
or like:
<div id="one">
<!--maybe some elements-->
<div id="two"></div>
<!---->
</div>
In the first case (#one and #two are siblings, that is they are on the same level = have the same parent), you use the general sibling combinator (~), like this:
#one:hover ~ #two { /* style changes */ }
DEMO for the case when #one and #two are siblings and #one is before #two in the HTML.
In the second case (#two is a descendant of #one), you use:
#one:hover #two { /* style changes */ }
DEMO for the case when #two is a descendant of #one.
However, if you wish to change an element that is before #one in the HTML, then that is currently (meaning that this could change in the future) impossible with CSS alone (if you would like to know why, then this article offers an explanation).
But in this case, when #two is before #one in the HTML, you can do it with JavaScript. For instance, if the opacity of #two is initially 0, then you could change it to 1 when hovering #one using:
var one = document.getElementById('one'),
two = document.getElementById('two');
one.addEventListener('mouseover', function(){
two.style.opacity = 1;
}, true);
one.addEventListener('mouseout', function(){
two.style.opacity = 0;
}, true);
DEMO
And if you're using a library like jQuery, then it gets even easier:
$('#one').hover(function(){
$('#two').css({'opacity': 1})},
function(){
$('#two').css({'opacity': 0})
});​​
DEMO
Use a combination of the :hover selector and the ~ General Sibling selector:
div.margin:hover ~.margin2
{
background: #00f;
}
Hover over div 2 and you'll see the other div change.
For this to work, the divs must be siblings (have the same parent element).
http://jsfiddle.net/Kyle_Sevenoaks/mmcRp/

Resources