CSS hover does not affect on other element - javascript

CSS :hover works when I use it for it's own element, but when i tried to affect another element, it had no effect.
For example, when I hover this button, the hidden links should appear, but they do not.
.dropdown {
position: relative;
display: inline-block;
border: 1px solid black;
width: 200px;
}
.dropbutton {
width: 100%;
height: 60px;
color: white;
background: #017678;
border: none;
}
.dropcontent a {
color: black;
text-align: center;
line-height: 40px;
text-decoration: none;
height: 40px;
background-color: #DDD;
border-width: 0 0 1px 0;
border-style: solid;
border-color: #9fa0a8;
display: none;
}
a:last-of-type {
border: none;
}
.dropbutton:hover .dropcontent {
display: block;
}
<div class="dropdown">
<button class="dropbutton">SHOW CONTENT</button>
<div class="dropcontent">
c1
c2
c3
</div>
</div>

A space is a descendant combinator. It targets descendants, but the div is not a descendant of the button, it is a sibling.
You need to use the adjacent sibling combinator instead: a plus sign.
You also need to target the links (which are descendants of .dropcontent so you should use a descendant combinator there) since it is those which you have set display: none on and not the div.
.dropbutton:hover + .dropcontent a {

Are you using Javascript to do this?
var button = document.getElementsByClassName('.dropbutton')[0],
menuContent = docuemnt.getElementsByClassName('.dropcontent')[0];
button.onmouseover = function(event) {
menuContent.style.display['block'];
}
button.onmouseout = function(event) {
menuContent.style.display['none'];
}
With a slight change to your CSS: .dropbutton should have display: none, and you should remove the display: none from .dropcontent a

I'd move the display: none; to the .dropcontent itself - as it now pertains to its anchors, that is, links, and as such, neither current answer would work -, then use
.dropbutton:hover + .dropcontent
{
display: block;
}
But you must not add anything between dropbutton and dropcontent afterwards, or it will not work any more.

Related

CSS style partially applying to button in React component

I have a button with a className 'actions'
This button shows the
css styling from '.actions' but not '.actions button' . I expect both to be included.
This syntax here works for every element except the button.
The full code is at: https://github.com/keithmacinnis/for-play-activity-browser
Activity.module.css
.item {
margin: 1rem 0;
}
.image {
width: 100%;
height: 20rem;
overflow: hidden;
border-top-right-radius: 6px;
border-top-left-radius: 6px;
}
.image img {
width: 100%;
object-fit: cover;
}
.content {
text-align: center;
padding: 1rem;
}
.content h3 {
font-size: 1.25rem;
color: #2c292b;
}
.actions {
padding: 1.5rem;
text-align: center;
}
.actions button {
font: inherit;
cursor: pointer;
color: #77002e;
border: 1px solid #77002e;
background-color: transparent;
padding: 0.5rem 1.5rem;
border-radius: 4px;
}
.actions button:hover,
.actions button:active {
background-color: #ffe2ed;
}
Activity.js
import css from "./Activity.module.css";
import Card from "./Card";
function Activity(props) {
return (
<li className={css.item}>
<Card>
<div className={css.image}>
<img src={props.activity.image} alt={props.activity.title} />
</div>
<div className={css.content}>
<h3>{props.activity.title}</h3>
<address>{props.activity.address}</address>
<p>{props.activity.description}</p>
</div>
<div>
<button className={css.actions}>Join Activity</button>
</div>
</Card>
</li>
);
}
export default Activity;
Again, I'm unsure why my button receives the stylings for padding and text-align, but the eight properties that follow are ignored.
I do not have much experience with creating selector combinations that include an element type and className, but I just did a little experimenting on my own, and it appears that these may be considered sibling selectors (as opposed to one being the child of the other). Also, it seems like the element type may have to come before the className.
It looks like if you write the selectors like one of these two ways, it should work:
button ~ .actions {
*styles*
}
button + .actions {
*styles*
}
You can read more about combinators here:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
To use .class selector for a specific element. You need Start with the element name first, then write the period (.) character, followed by the name of the class... like this
Button.actions {
font: inherit;
cursor: pointer;
color: #77002e;
border: 1px solid #77002e;
background-color: transparent;
padding: 0.5rem 1.5rem;
border-radius: 4px;
}
If that doesn't work. It might be a problem with the browser using your previous css version from the cash and not the updated styling. To solve it use this:
Ctrl + F5 On Mac OS (in Chrome) use: Cmd + Shift + R .
This will force your browser to reload and refresh all the resources related to the website's page.
It was fixed by this change in Activity.js :
new code:
<div className={css.actions}>
<button >Join Activity</button>
</div>
old code:
<div>
<button className={css.actions}>Join Activity</button>
</div>

Display a menu when hovering on the last character in the input in React

I am currently working on a form using React-Bootstrap that has a body that takes a message. This message shall include some tags selected from a dropdown menu. The thing is, this dropdown is to be displayed when the user enters an & and then, the user chooses an option from the menu that will replace the ampersand. I handled almost everything except the part of displayed the menu. How can I always show the menu at the last character entered by the user and also, how can I display it when hovering on this character. For example,
"Hi Dear, today we are going to work on &[The menu has to be displayed here when hovering on the ampersand]"
To be honest, I am quite confused and I just need to figure out how I should start. If there could be anything that helps, I'd be very grateful. Thanks in advance.
Regards.
Here is something i came up with.
To achieve this, first thing i thought of was to detect the caret position inside input or textarea.
I found this library and it worked perfectly.
https://github.com/bubkoo/get-cursor-position
Next task was to figure out how to place a menu inside input or textarea. For that i simply made a parent div and i set input 100% width and height of it & then we can place using any html tag inside that div using position: absolute and it will work like we adding stuff inside input tag.
The menu was added with top & left i got using that library. Rest of the code is basic, you can simple figure that out just checking it below.
Here is the code:
const menu = document.querySelector('.menu')
function showMenu(element) {
let lastChar = element.value[element.value.length - 1],
caret = getCaretCoordinates(element, element.selectionEnd);
if (lastChar === "&") {
menu.style.display = 'block';
menu.style.left = caret.left + 20 + 'px'
menu.style.top = caret.top + 20 + 'px'
} else {
menu.style.display = 'none'
}
}
function copyText(text) {
const input = document.querySelector('#input')
input.value += " " + text
menu.style.display = 'none'
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
transition: all 0.3s ease;
}
body {
height: 100vh;
width: 100vw;
display: grid;
place-content: center;
background-color: blueviolet;
}
.parent {
position: relative;
width: 500px;
height: 120px;
}
#input {
background-color: white;
width: 100%;
height: 100%;
border: none;
border-radius: 10px;
padding: 20px;
}
#input:focus {
border: 0;
outline: none;
}
.menu {
display: none;
position: absolute;
background-color: black;
color: white;
width: 100px;
}
.menu li {
text-align: center;
cursor: pointer;
height: 60px;
list-style: none;
display: grid;
place-content: center;
padding: 10px;
}
li:hover {
background: white;
;
color: black;
border: 1px solid black
}
<div class="parent">
<textarea id="input" oninput="showMenu(this)"></textarea>
<div class="menu">
<li onclick='copyText(this.innerText)'>Mango</li>
<li onclick='copyText(this.innerText)'>Banana</li>
<li onclick='copyText(this.innerText)'>Apple</li>
<li onclick='copyText(this.innerText)'>Orange</li>
<li onclick='copyText(this.innerText)'>Grapes</li>
</div>
</div>
<script src="https://rawgit.com/component/textarea-caret-position/master/index.js"></script>

Css class active

I have small problem with css and jQuery. I have 2 buttons and I want to set the background of the one clicked to blue, and I want to do this with 'active' css property. It is not working for some reason. Whenever the button is not active anymore, it loses the background color. Here is the code:
HTML:
<div id = 'hey'>
<div class = 'b' id = 'b1' href="#">Button one</div>
<div class = 'b' id = 'b2' href="#">Button Two</div>
</div>
CSS:
body,html {
font: bold 14px/1.4 'Open Sans', arial, sans-serif;
background: #000;
}
#hey {
margin: 150px auto 0;
padding: 0;
list-style: none;
display: table;
width: 600px;
text-align: center;
}
.b {
color: #fff;
text-transform: uppercase;
text-decoration: none;
letter-spacing: 0.15em;
display: inline-block;
padding: 15px 20px;
position: relative;
}
.b:active {
background-color: blue;
}
JS:
$(".b").click(function() {
$(this).addClass('active');
});
:active is a pseudo-class meaning "while being activated" (typically while the mouse button is held down over it).
You are giving it a class active so you need to use a class selector: .active (with a . not a :).
I suggest not using class names which match pseudo-class names as it is an easy source of confusion.
:active is pseudo-element and you are trying to add active as a class. So the CSS should be
.b.active {
background-color: blue;
}

How can i get 2 classes by id inside the same function

I need to target two div elements and toggle their classes simultanouesly.
I understand that I can get multiple divs "by ID" by using .querySelectorAll
but when I get to .classlist.toggle ("NewClassName"); how can I target two classes??
So here's some code:
#small-div{
background-color:#aaaaaa;
border: 3px solid #aaaaaa;
padding: 0px 0px 0px 0px;
margin: auto 10px auto auto;
border-radius: 10px;
overflow: auto;
}
.tobetoggled{
width: 45%;
float: left;
}
#small-div2{
background-color:#aaaaaa;
border: 3px solid #aaaaaa;
padding: 0px 0px 0px 0px;
margin: auto 10px auto auto;
border-radius: 10px;
overflow: auto;
}
.tobetoggled2{
width: 45%;
float: right;
}
.toggletothis{
width: 100%;
float: left;
position: fixed;
display: block;
z-index: 100;
}
.toggletothis2{
width: 100%;
float: left;
position: fixed;
display: block;
z-index: 100;
}
.whensmalldivistoggled{
display: none;
}/* when small-div is clicked, small-div toggles to class "tobetoggled" while small-div 2 simultaneously toggles to class "whensmalldivistoggled" (the display none class) */
<div id="container">
<div class="tobetoggled" onclick="function()" id="small-div">
</div>
<div class="tobetoggled2" onclick="separatefunction()" id="small-div2">
</div>
</div> <!-- end container -->
<script>
function picClicktwo() {
document.querySelectorAll("small-div, small-div2").classList.toggle("toggletothis, whensmalldivistoggled");
}
</script>
So as you can see one div is on the right, the other is on the left, each set to 45% width. So if I toggle one div to 100% width the browser still respects the other divs space instead of taking the whole 100%.
So I'm thinking if I can get the div on the right ,for example, to not display when the div on the left is toggled, it will be out of the way so the left div can take all 100%
Maybe im going about this the wrong way. Any help is welcome. Thanks.
You can create a single javascript function that sets appropriate classes on each element. Since you have only two elements it is not too complex.
HTML
<div id="container">
<div id="lefty" onclick="toggle('lefty', 'righty')">Lefty</div>
<div id="righty" onclick="toggle('righty', 'lefty')">Righty</div>
</div>
JS
function toggle(target, other)
{
var t = document.getElementById(target);
var o = document.getElementById(other);
if (!t.className || t.className == "inative")
{
t.className = "active";
o.className = "inactive";
}
else
{
t.className = "";
o.className = "";
}
}
CSS
#container {
background-color: lightgreen;
padding: 15px 0;
}
#container div {
color: white;
width: 45%;
display: inline-block;
}
#lefty {
background-color: blue;
}
#righty {
background-color: purple;
}
#container div.active {
width: 90%;
}
#container div.inactive {
display:none;
}
https://jsfiddle.net/dLbu9odf/1/
This could be made more elegant or capable of handling more elements with something like toggle(this) and then some DOM traversal and iteration in javascript, but that's a bit beyond scope. If that were the case I would recommend jQuery.

Show one element if another is above a certain height

I have a following HTML:
<span class="day-number">{{day-number}}</span>
<div class="event-box">
<div class="event-container">
</div>
<div class="more-events">more ...</div>
</div>
Event-container is filled with an unknown number of .event elements like the following:
<div class="event">{{event-name}}</div>
I want to show or hide the .more element based on if the .event-container has a height of over 76px (equal to the height of four .event elements stacked).
The styling for the above elements:
.event {
text-align: left;
font-size: .85em;
line-height: 1.3;
border-radius: 3px;
border: 1px solid #3a87ad;
background-color: #3a87ad;
font-weight: normal;
color: whitesmoke;
padding: 0 1px;
overflow: hidden;
margin-bottom: 2px;
cursor: pointer;
}
.event-box {
max-height: 76px;
overflow: hidden;
position:relative;
}
.event-box .more-events {
height: 10px;
position: absolute;
right: 0;
bottom: 10px;
display: none;
z-index: 5;
}
No styling for .event-container
I can do what I want with Javascript (jQuery):
$(".event-box").each(function(){
var $this = $(this);
if($this.children(".event-container").height() > 76){
$this.children(".more-events").css("display", "block");
} else {
$this.children(".more-events").css("display", "");
}
});
And run that every time a make a change, but I'd rather do it with CSS.
Is this possible? Maybe with pseudo elements or media queries or something?
JSFIDDLE: http://jsfiddle.net/pitaj/LjLxuhx2/
If changing the markup is acceptable there is a possibility to achieve a somewhat similarly looking page without using JavaScript to show or hide, here is the Fiddle
I have removed <div class="more-events">more ...</div> line and made elements of event class to get hide when it is necessary I also made them to appear when hovering over more ... .
The CSS I have added:
.event:nth-child(n){
display: none;
}
.event:nth-child(1),.event:nth-child(2),.event:nth-child(3),.event:nth-child(4){
display: block;
}
.event:nth-child(5){
text-indent: -9999px;
position: relative;
display: block;
color: black;
border: none;
background-color: #FFF;
}
.event:nth-child(5)::before{
position: absolute;
text-indent: 0px;
content: "more ...";
display: block;
}
.event:nth-child(5):hover{
position: static;
text-indent: 0;
border: 1px solid #3a87ad;
background-color: #3a87ad;
color: whitesmoke;
}
.event:nth-child(5):hover::before{
display:none;
}
.event:nth-child(5):hover ~ .event:nth-child(n){
display: block;
}
And for .event-box class I have commented out max-height: 76px; because in my browser 76px was not equal to the height of four .event elements stacked. Also removed update function.
I dont think it's possible using css only. but for better approach in what you are trying to do.instead of using max-height for .event-box I use this css which is add display:none to +4.event on your event container:
.event-box .event-container .event:nth-child(n+5){
display: none;
}
and now when it's more than 4 .event your more text appears. FIDDLE
UPDATE:
HERE I make little change in you js as well and make it more professional,
while you are using template to render the page, maybe you can do it as follow
<div class="event-container">
{{#each events}}
<div class="event">{{event-name}}</div>
{{/each}}
</div>
{{#if canshowmore}}
<div class="more-events">more ...</div>
{{/if}}
and
function canshowmore() {
return events.length >= 4;
}

Categories

Resources