How to change a svg image along with text with hover in CSS - html

I tried to change my svg image and text on hover and it doesn't work how I want it. I want the moment my mouse crosses over any of these 2 (svg or text) to change both.
Maybe I made a mistake in the html structure or maybe in css.
Please if you can help me, thanks in advance.
.logout-image {
mask: url("../../../assets/images/log-out.svg");
background-color: #62799D;
width: 20px;
height: 20px;
margin-right: 20px;
margin-left: 20px;
}
.logout-container {
display: flex;
flex-direction: row;
align-items: center;
padding: 8px 0px 8px 24px;
width: 100%;
height: 60px;
position: static;
left: 0px;
top: 280px;
color: #62799d;
margin-top: 35vh;
}
.logout-container:hover {
background: #0c2e6e;
color: white;
}
.logout-image:hover{
background: white;
}
<ul className="SidebarList">
{sidebarData.map((value, key) => {
return (
<li
className="row"
key={key}
onClick={() => {
window.location.pathname = value.link;
}}
>
{" "}
<div className="icon">{value.icon}</div>{" "}
<div className="title">{value.title}</div>
</li>
);
})}
{" "}
{" "}
//here is the problem
<li className='logout-container'>
<div className="logout-image"></div>
<div className="title" >Logo Out</div>
</li>
//until here
</ul>
This is how I wanted to change with hover:
target result
And this is how it is working right now:
current result
The background changes only if I cross over my svg image:
example here

Add this:
.logout-container:hover > .logout-image{
background: white;
}
It turns the image and words white when logout-container is hovered.

Related

Preventing a dropdown from appearing behind other dropdowns

I'm building a custom dropdown. The real thing is going to have all the necessary ARIA attributes of course, but here's the barebones version:
[...document.querySelectorAll('.select')].forEach(select => {
select.addEventListener('click', function() {
select.nextElementSibling.classList.toggle('visible');
});
});
.dropdown {
position: relative;
width: 16rem;
margin-bottom: 2rem;
}
.select {
display: flex;
align-items: center;
height: 2rem;
background-color: #ccc;
}
.popup {
display: none;
position: absolute;
left: 0;
right: 0;
height: 10rem;
background-color: #eee;
box-shadow: 0 0 0.5rem red;
}
.popup.visible {
display: block;
}
<!doctype html>
<html>
<body>
<div class="dropdown">
<div class="select">Button 1 ▼</div>
<div class="popup">Popup 1</div>
</div>
<div class="dropdown">
<div class="select">Button 2 ▼</div>
<div class="popup">Popup 2</div>
</div>
</body>
</html>
The obvious issue is that, when you open the first dropdown, popup 1 appears behind button 2. The obvious solution would be to give .popup a z-index, and make it an absurdly large value like 999 to make sure it appears above other elements on the page as well.
However, in my case, I would also like the popup to appear behind its corresponding button (in order to hide its box-shadow).
If I give the button a z-index greater than the popup's, the original problem returns: popup 1 appears behind button 2. If I instead give the z-index: 999 to the entire .dropdown and create a new stacking context, the same thing happens.
Is there any way I can meet my two requirements at the same time (popup behind its button, and only that one, but above everything else on the page)?
You could track the dropdown .open state. And use that to toggle the display property of its child .popup. However the .dropdown.open state will have a z-index:1, that way it will always show up on top of elements below it.
[...document.querySelectorAll('.select')].forEach(select => {
select.addEventListener('click', function(event) {
const {
target: {
parentElement: activeDropdown
}
} = event;
activeDropdown.classList.toggle('open');
const container = select.parentElement.parentElement;
const dropdowns = container.querySelectorAll('.dropdown');
Array.from(dropdowns).forEach(item => {
if (item !== activeDropdown) {
item.classList.remove('open')
}
})
});
});
.dropdown {
position: relative;
width: 16rem;
margin-bottom: 2rem;
}
.dropdown.open {
z-index: 1;
}
.dropdown.open>.popup {
display: block;
}
.select {
display: flex;
align-items: center;
height: 2rem;
background-color: #ccc;
}
.popup {
display: none;
position: absolute;
left: 0;
right: 0;
height: 10rem;
background-color: #fff;
box-shadow: 0 0 0.5rem red;
}
<!doctype html>
<html>
<body>
<div class="dropdown">
<div class="select">Button 1 ▼</div>
<div class="popup">Popup 1</div>
</div>
<div class="dropdown">
<div class="select">Button 2 ▼</div>
<div class="popup">Popup 2</div>
</div>
</body>
</html>

SCSS - Conditional include not working and all the blocks gets executed

I am trying to do conditional include in scss. Here is the code:
HTML
<div class="test" data-active data-label data-comment >1</div>
<div class="test" data-active data-label>2</div>
<div class="test" data-active data-comment >3</div>
<div class="test" data-active data-comment data-label>4</div>
<div class="test" data-active>5</div>
SCSS
.test[data-active]{
background : red;
width: 50px;
height: 50px;
display: inline-block;
$margin: 0px;
&[data-label]{
background : blue;
$margin: $margin + 10px;
}
&[data-comment]{
background: yellow;
$margin: $margin + 10px;
}
&[something]{
$margin: $margin + 100px;
}
margin-right : $margin;
}
Here is the codepen link: https://codepen.io/gaurav-neema/pen/VwpPBxY
In the code, you can see that even if the element does not contain the attribute, all the blocks get executed and the margin is included.
Can anyone help in indentifying what's wrong with the code?
You are redefining $margin every time, you cannot use selectors like if statements.
Redefining with:
$margin: $margin + 10px;
$margin: $margin + 100px;
You are setting all margin-right: 100px;
I think you might want:
SCSS
$margin: 0px;
.test[data-active] {
background: red;
width: 50px;
height: 50px;
display: inline-block;
&[data-label] {
background : blue;
margin: $margin + 10px;
}
&[data-comment] {
background: yellow;
margin: $margin + 10px;
}
&[something] {
margin: $margin + 100px;
}
margin-right: $margin;
}
What you are looking for is CSS custom properties. SCSS is not dynamic and there for renders at compile. CSS custom properties are dynamic so they get applied once the condition is for filled, meaning when your class is applied it will change the value then.
Read about the difference at:
css-tricks.com
Read about CSS custom properties at:
MDN
ishadeed.com
daverupert.com
This is just 3 of so many articles about the subject.
Now demo time, I changed the property to be background-color to make it more clear for the demo.
.test[data-active] {
--background-color: aqua;
background: var(--background-color);
width: 50px;
height: 50px;
display: inline-block;
}
.test[data-label] {
--background-color: deeppink;
}
.test[data-something] {
--background-color: deepskyblue;
}
<div class="test" data-active data-label data-comment>1</div>
<div class="test" data-active data-label>2</div>
<div class="test" data-active data-comment>3</div>
<div class="test" data-active data-comment data-label>4</div>
<div class="test" data-active data-something>5</div>

How to fix mat-list-item not taking full space of row

Hello guys I rendering an article.component.html inside my article-list-component.html in a list when I do it in plain HTML it renders just fine (see picture 1):
Title - author - Date
Here is my article-list.component.html
<ul>
<li *ngFor="let article of data_array">
<a [href]="article.url" class="undecorateda" target="_blank">
<app-article [data]='article'></app-article>
</a>
</li>
</ul>
but when I try to use angular-material list the component renders all to the left like this (see picture 2):
Title-author-Date
Here is my article-list.component html:
<mat-list>
<mat-list-item *ngFor="let article of data_array">
<a [href]="test">
<app-article [data]='article' (click)="printURL(article.url)"></app-article>
</a>
</mat-list-item>
</mat-list>
when I use the plain HTML in the article-list.component.html it renders as I want it to do, but if I use the material code inside article-list.component.html it doesn't render properly
this is the article.component.html
<div class='article-container'>
<div class='title-container'>
{{data.title}}
<div class='author-container'>
-{{data.author}}-
</div>
</div>
<div class='date-container'>
{{formatDay(data.created_at)}}
</div>
<div class="actions-container" id="deletebtn">
<button mat-icon-button color="warn" (click)="deleteArticle(data._id)">
<mat-icon>delete_forever</mat-icon>
</button>
</div>
</div>
this is the article.component.css file:
.article-container {
display: grid;
grid-auto-flow: column;
grid-template-columns: 10fr 2fr 1fr;
height: 50px;
background-color: #fff;
border-bottom: 1px solid #ccc;
align-items: center;
padding: 0 15px;
}
.article-container>* {
grid-row: 1/2;
}
.article-container #deletebtn {
display: none;
}
.article-container:hover {
background-color: #fafafa;
}
.article-container:hover #deletebtn {
display: block;
}
.title-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
color: #333;
font-size: 13pt;
}
.author-container {
color: #999;
font-size: 10pt;
margin-top: 3px;
}
.date-container {
color: #333;
font-size: 13pt;
}
.title-container div {
padding: 0 15px;
}
Basically what I want is to use material-angular list inside the article-list.component.html and that it render good like in picture 1
==========================================
If you add a width of 100% to the article component itself it should ensure the component takes the whole width and the list will the whole width as well.
:host {
width: 100%;
}
Take a look at this example here to see the list taking 100% of the width.

json not displayed properly --

I am trying to do my json assignment on creating 4 card profiles - each with a picture and background profile.
I seem to manage to create the 4 picture properly but not the background profile. I only managed to displayed the 1st background profile initially using absolute and relative positioning, so I changed to float and managed to display all 4 background profiles but at the bottom, instead of the right side of each picture profile.
I did the exact same thing on both picture and background profile but not sure why only the picture works. Would appreciate and thanks in advance for your help and inputs.
let pictureHTML = data.map(function(data) {
return data = `
<div class="name-title-bottom>">
<img class="profile-img" ${data.picture}>
<li class="data-name">${data.name}</li>
<li class="data-jobTitle">${data.jobTitle}</li>
</div>
`
});
let dataHTML = data.map(function(data) {
 return data =`
<div class="right-side">
<ul>
<li class="data-jobTitle">Company: ${data.Company}</li>
<li class="data-name">School: ${data.School}</li>
<li class="data-name">Experience: ${data.Experience}</li>
<li class="data-jobTitle">School: ${data.School}</li>
<li class="data-name">Major: ${data.Major}</li>
<li class="data-jobTitle">Email: ${data.Email}</li>
<li class="data-email">${data.LinkedInUrl}</li></ul><br></div>
`
});
$(".hook").append(pictureHTML);
$(".hook2").append(dataHTML);
});
.main{
// position: relative;
padding: 80px 80px 130px 10px;
display: inline-block;
.right-side{
display: inline-block;
float: right;
// position: absolute;
// top: 180px;
// right: 0px;
width: 250px;
height: 200px;
padding: 10px;
}
.name-title-bottom{
// position: absolute;
// bottom: 0;
// left: 200px;
float: left;
padding: 30px 30px 30px 40px;
text-align: center;
display: inline-block;
}
}

Basic vertical center in CSS behaving strangely on floated element

So i've come to live by these 3 CSS rules that almost always vertically center any block level element:
.vertically-center {
position: relative;
top: 50%;
transform: translateY( -50% );
}
It works often. But in the case of this particular layout I'm building it is pushing the elements too high ( partially off the screen ) and I don't know why.
This is how the webpage looks before adding my vertically-center class to my portrait-container div:
And this code snippet is how it appears after adding the vertically-center class to the portrait-container div:
.clearfix:after {
content: "";
display: block;
clear: both;
}
.vertically-center {
position: relative;
top: 50%;
transform: translateY( -50% );
}
body {
overflow: hidden;
}
main {
padding-top: 50px;
background: #fafafa;
text-align: left;
}
.portrait-container {
float: left;
}
img {
width: 150px;
border-radius: 50%;
}
.about-container {
width: 70%;
float: right;
}
<main class="clearfix">
<div class="portrait-container vertically-center">
<img src="http://i.imgur.com/Eb5sRZr.jpg" alt="Portrait of John Lesko">
</div>
<div class="about-container">
<h3>About</h3>
<p>
Hi, I'm John Lesko! This is my art portfolio where I share all
of my favorite work. When I'm not creating things, I enjoy excercising,
playing video games, drinking good Kool Aid, and more.
<br><br> If you'd like to follow me on Twitter, my username is
#jletsgo.
</p>
</div>
</main>
I just want the image container to be vertically-centered regardless of the height of it's parent. Help? Inspecting elements gave me no insights.
Edit: Just to show how this has always worked for me in the past. Here is a jsfiddle: https://jsfiddle.net/9kyjt8ze/4/. Why does it work for me there and not here?
Related question: What does top: 50%; actually do on relatively positioned elements?
Your CSS was not bad but I didn't get along with it. So here is another approach on how you could solve it, maybe it helps also. It will always center the image vertically and does not matter how much text the box on the right will have. The colored borders are just there to help show the visual effect of the box sizes.
* {
box-sizing: border-box;
}
.portrait-container {
position: relative;
margin: 20px 0;
}
.portrait-container:after {
content: '';
display: block;
clear: both;
}
.portrait-container img {
position: absolute;
top: calc(50% - 80px); /* 50% from top minus half img height*/
width: 150px;
height: 160px;
border-radius: 50%;
float: left;
}
.portrait-container {
border: solid 2px orange;
}
.portrait-container .about-container {
border: solid 2px green;
padding: 0 50px;
margin-left: 150px; /* this elements should be at least 150px away from left side */
width: calc(100% - 150px); /* the max width this element should have to be placed */
/* next to the image is the total width(100%) - the image width */
}
<main>
<div class="portrait-container">
<img src="http://i.imgur.com/Eb5sRZr.jpg" alt="Portrait of John Lesko">
<div class="about-container">
<h3>About</h3>
<p>
Hi, I'm John Lesko! This is my art portfolio where I share all
of my favorite work. When I'm not creating things, I enjoy excercising,
playing video games, drinking good fruit punch, and more.
<br><br> If you'd like to follow me on Twitter, my username is
#jletsgo.
</p>
</div>
</div>
</main>
<main>
<div class="portrait-container">
<img src="http://i.imgur.com/Eb5sRZr.jpg" alt="Portrait of John Lesko">
<div class="about-container">
<h3>About</h3>
<p>
Hi, I'm John Lesko! This is my art portfolio where I share all
of my favorite work. When I'm not creating things, I enjoy excercising,
playing video games, drinking good fruit punch, and more.
<br><br> If you'd like to follow me on Twitter, my username is
#jletsgo.
</p>
<p>
Hi, I'm John Lesko! This is my art portfolio where I share all
of my favorite work. When I'm not creating things, I enjoy excercising,
playing video games, drinking good fruit punch, and more.
<br><br> If you'd like to follow me on Twitter, my username is
#jletsgo.
</p>
</div>
</div>
</main>
UPDATE
Edit: Just to show how this has always worked for me in the past. Here is a jsfiddle: https://jsfiddle.net/9kyjt8ze/4/. Why does it work for me there and not here?
The black circle is the only element there in the Fiddle, there's no obstructions. In the code you are having trouble with, you have many elements either in the way or wrapped around other elements trapping them. Your ruleset will work if you start stripping away the layers. Or you can just add a property and change another property as per Snippet 1.
One important note a relative element is actually occupying the original spot, so if given a left:40px it appears to be moved 40px to the left, but in reality it still occupies the space 40px to the right of where it appears to be. So relative elements are not really in a flow different from static elements. Therefore they are affected by and affect static layout, it's just not noticeable normally because they stack with z-index.
Snippet 2 is an interactive demo, I figured maybe that'll help explain things better.
The 3 CSS ruleset is a common way to vertically align elements, but it was originally position: absolute instead of position:relative and it had to be in another positioned element if I remember correctly.
REFERENCE
Specific Ruleset
W3Schools
MDN
SOLUTION
.vertically-center {
/* Changed to absolute from relative */
position: absolute;
top: 50%;
transform: translateY( -50% );
}
main {
/* Added position: relative */
position: relative;
padding-top: 50px;
background: #fafafa;
text-align: left;
}
SNIPPET 1
.vertically-center {
position: relative;
top: 50%;
transform: translateY( -50%);
}
body {}
main {
padding-top: 50px;
overflow: scroll;
background: #fafafa;
text-align: left;
}
img {
width: 150px;
border-radius: 50%;
float: left;
}
.about {
width: calc(100% - 150px);
float: right;
}
<main class="clearfix">
<img src="http://i.imgur.com/Eb5sRZr.jpg" alt="Portrait of John Lesko" class="vertically-center">
<article class="vertically-center about">
<h3>About</h3>
<p>
Hi, I'm John Lesko! This is my art portfolio where I share all of my favorite work. When I'm not creating things, I enjoy excercising, playing video games, drinking good Kool Aid, and more.</p>
<p>If you'd like to follow me on Twitter, my username is
#jletsgo.
</p>
</article>
</main>
SNIPPET 2
$('#b1').click(function() {
$('body').toggleClass('R S');
});
$('#b2').click(function() {
$('#N1,#N2,#N3').toggleClass('N M');
});
$('input[id$="2"]').on('input', function() {
var grp = "." + $(this).attr('class');
var num = parseInt($(this).val(), 10);
grp !== '.S' ? $('section' + grp).css('left', num + '%') : $('section.S').css('margin-left', num + '%');
});
$('input[id$="3"]').on('input', function() {
var grp = "." + $(this).attr('class');
var num = parseInt($(this).val(), 10);
grp !== '.S' ? $('section' + grp).css('top', num + '%') : $('section.S').css('margin-top', num + '%');
});
html,
body {
height: 100%;
width: 100%;
}
body {
overflow: scroll;
font: 400 12px/1.2 Consolas;
}
section {
width: 50px;
height: 150px;
border: 2px dashed grey;
text-align: center;
color: white;
}
.R {
position: relative;
background: rgba(0, 0, 255, .3)
}
.A {
position: absolute;
background: rgba(255, 0, 0, .3)
}
.F {
position: fixed;
background: rgba(0, 255, 0, .3)
}
.S {
position: static;
background: rgba(122, 122, 0, .3)
}
.N {
position: absolute;
background: yellow;
color: blue;
}
.M {
position: relative;
background: black;
color: yellow;
}
#R1 {
left: 20%;
top: 3%;
z-index: 1;
}
#A1 {
left: 42%;
top: 44%;
z-index: 2;
}
#F1 {
right: 20%;
top: 44%;
z-index: 3;
}
#S1 {
margin-left: 0;
margin-top: -28%;
}
#N1 {
bottom: 0;
right: 0;
width: 25px;
height: 80px;
z-index: 4;
}
input {
width: 6ex;
position: static !important;
}
button {
font: inherit;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body class='S'>
<fieldset>
<button id='b1'>Body Relative/Static</button>
<button id='b2'>Nested Absolute/Relative</button>
<br><br> RLeft
<input id='R2' class='R' type='number' value='20'> RTop
<input id='R3' class='R' type='number' value='3'> ALeft
<input id='A2' class='A' type='number' value='44'> ATop
<input id='A3' class='A' type='number' value='44'><br> FLeft
<input id='F2' class='F' type='number' value='64'> FTop
<input id='F3' class='F' type='number' value='44'> SLeft
<input id='S2' class='S' type='number' value='0'> STop
<input id='S3' class='S' type='number' value='-28'><br> NLeft
<input id='N2' class='N' type='number' value='45'> NTop
<input id='N3' class='N' type='number' value='45'>
</fieldset>
<section id='R1' class='R'>RELATIVE
<section id='N1' class='N'>N<br>E<br>S<br>T<br>E<br>D</section>
</section>
<section id='A1' class='A'><br><br><br>ABSOLUTE</section>
<section id='F1' class='F'><br><br>FIXED</section>
<section id='S1' class='S'><br><br><br><br><br>STATIC</section>
</body>
You can achieve this by using flexboxwith a lot less code. The below code will do the trick.
.clearfix {
display: flex;
align-items: center;
}
img {
width: 150px;
border-radius: 50%;
}
.about-container {
width: 70%;
padding-left: 30px;
}
Check it out in codepen http://codepen.io/anon/pen/OWYxrb