Fellow Coders,
I encountered a problem while putting dropdown menu into my app's navigation. When I drag my mouse over my dropdown element, menu below expands together expanding div element above (which is dropdown menu's name) and pushing all other items in navigation's menu to the right side. Here is my code:
const listItems = links.map((link_name) =>
<li className="nav-item" key={link_name}>
<div className="nav-link"><DropDown name={link_name} /></div>
</li>
);
return (
<nav className="navbar-light" style={{ backgroundColor: '#333333' }}>
<div>
<div className="container-fluid">
<Link to="/" className="navbar-brand">
<img alt="dribbble" style={styles.style_img} src={"http://www.underconsideration.com/brandnew/archives/dribbble_logo_detail.png"} />
</Link>
<ul className="nav navbar-nav" style={styles.style_l}>
{listItems}
</ul>
</div>
<ul className="nav navbar-nav" style={styles.style_r}>
{this.renderLinks()}
<li className="nav-item" key={10}>
<input type="search" ref="city" placeholder="Search"/>
</li>
</ul>
</div>
</nav>
);
const styles = {
style_r: {
margin: 10,
top: 5,
right: 17,
bottom: 20,
left: 'auto',
position: 'fixed',
},
style_l: {
margin: 5,
top: 10,
left: 134,
bottom: 20,
position: 'absolute',
},
style_img: {
margin: 5,
left: 10,
width: 100,
height: 42,
}
};
dropdown is defined as:
if(this.state.menuActive) {
menu = <div>
<ul className="drop">
<li>First Item </li>
<li>Second Item </li>
<li>Third Item </li>
</ul>
</div>
} else {
menu = "";
}
return (
<div id = "menu">
<div id = "dropdown_name" style={{ color: '#F5F5F5' }} onMouseOver = { this.toggleMenu } onMouseLeave = { this.toggleMenu }>{this.props.name}</div>
<ReactCSSTransitionGroup transitionName = "menu" transitionEnterTimeout={1000} transitionLeaveTimeout={1000}>
{menu}
</ReactCSSTransitionGroup>
</div>
)
if I put style={{ position: absolute }} on div (dropdown_name), in my nav bar every element collides into one gibberish weird looking unreadable name...
and here's mine css:
.menu-enter {
max-height: 0px;
-webkit-transition: max-height;
overflow: hidden;
width: 100%;
}
.menu-enter.menu-enter-active {
height: auto;
max-height: 100px;
width: 100%;
}
.menu-leave {
max-height: 100px;
-webkit-transition: max-height;
width: 100%;
}
.menu-leave.menu-leave-active {
overflow: hidden;
max-height: 0px;
width: 100%;
}
ul.drop {
margin-top: 7px;
background-color: #333333;
color: #6D6D6D;
border: #333333 solid 7px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
width: 100%;
padding-left:0.4em;
font-size: 12pt;
list-style-type: none;
}
How can I prevent dropdown from expanding my dropdown's name above? I want that my divs that represent dropdown's names would remain the same width.
From MDN:
The absolutely positioned element is positioned relative to its nearest positioned ancestor (i.e., the nearest ancestor that is not static).
Keep your absolute positioning on the dropdown component, and place a position: relative; style on the dropdown's container component (nav-link). This will allow the dropdown to be positioned relative to it's containing nav link.
It seems like your issue with every element combining when you added the absolute position was because they were all being absolutely positioned to the body element.
Related
I'm having issues with an overlay navbar which is supposed to slide in from top.
Not sure why, but if i click the hamburger menu, the proper css class is applied, but the transition doesn't occur (it acts like a show/hidden).
However, if i change the top property value from the dev tool, it works as expected.
what am i missing?
Here's the react component
import React, { useState } from "react";
import NavMenuIcon from "../../public/svg/nav.svg";
import styles from '../../styles/Navbar.module.scss'
import Link from 'next/link'
function Navbar() {
const [menu, setToggle] = useState(false);
const toggleMenu = () => setToggle(!menu);
const Menu = props => (
<div className={ props.toggle ? `${styles.menu__container} ${styles.toggle}` : `${styles.menu__container}` }>
<div className={styles.menu__content}>
<ul className={styles.menu__list}>
<li className={styles.menu__item} onClick={toggleMenu}> <Link href="/"><span>Home</span></Link></li>
<li className={styles.menu__item} onClick={toggleMenu}> <Link href="/services"><span>Services</span></Link></li>
<li className={styles.menu__item} onClick={toggleMenu}> <Link href="/services#contact"><span>Contact</span></Link></li>
</ul>
</div>
</div>
);
return (
<div className={styles.navbar}>
<i>Meuartelie</i>
<NavMenuIcon className={styles.hamburger} onClick={toggleMenu} />
<Menu toggle={menu}></Menu>
</div>
);
}
export default Navbar;
and here's the css
#import './variables.scss';
.navbar {
box-sizing: border-box;
position: fixed;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 5%;
z-index: 5;
}
.menu__container {
font-family: 'Jokerman Std';
position: absolute;
top: -300px;
left: 0;
width: 100vw;
height: 300px;
z-index: -1;
background-image: url("../public/png/welcome_mobile.png");
background-color: black;
background-size: cover;
overflow: hidden;
transition: 850ms;
}
.menu__content {
font-size: 2rem;
display: flex;
align-items: center;
justify-content: center;
margin-top: 20%;
}
.menu__container.toggle {
top: 0;
transition: all 1s ease-in;
}
.menu__list {
width: 80%;
text-align: center;
list-style: none;
padding: 0px;
line-height: 2;
margin: 0px;
margin-bottom: 20px;
}
.menu__item {
transition: padding-left .7s ease, color .7s ease;
/* underline css*/
text-decoration: none;
position: relative;
}
.menu__item:hover {
color: $base-color;
padding-left: 20px;
cursor: pointer;
}
.menu__item:after {
content: '';
height: 2px;
/* adjust this to move up and down. you may have to adjust the line height of the paragraph if you move it down a lot. */
bottom: 0px;
/* center - (optional) use with adjusting width */
margin: 0 auto;
left: 0;
right: 0;
width: 40%;
background: #fff;
/* optional animation */
-o-transition:.5s;
-ms-transition:.5s;
-moz-transition:.5s;
-webkit-transition:.5s;
transition: .5s;
}
/* optional hover classes used with anmiation */
.menu__item:hover:after {
background: $base-color;
}
.hamburger {
z-index: 1000;
cursor: pointer;
}
This has to do with how react determines what to rerender.
Whenever react determines a new reference in the render tree, it automatically rerenders that element.
CSS transitions on the other hand will transform from a starting state, to the end state.
If the start and end are the same, no transition is applied.
So what's actually happening:
The button gets clicked.
The render tree is modified. specifically const Menu is assigned a new reference.
React removed any old elements from the dom, in this case <div class="menu__container">
React adds the new elements to the dom, in this case <div class="menu_container toggle">
the browser renders the element and applies the initial css rules. the element receives the top:0 as the initial state. there is no transition since the old element was removed.
How to fix it:
Make sure you React knows we're still rendering the same element, so it will update the existing dom element, instead of removing and adding a new element.
several ways to do this, the recommended way is to extract the element from the render function. The reference becomes static then
//extracted from render function:
const Menu = (props) => (
<div key='1' className={ props.toggle ? `menu__container toggle` : `menu__container` }>
<div className={'menu__content'}>
<ul className={'menu__list'}>
<li className={'menu__item'} onClick={props.toggleMenu}> <Link href="/"><span>Home</span></Link></li>
<li className={'menu__item'} onClick={props.toggleMenu}> <Link href="/services"><span>Services</span></Link></li>
<li className={'menu__item'} onClick={props.toggleMenu}> <Link href="/services#contact"><span>Contact</span></Link></li>
</ul>
</div>
</div>
);
function Navbar() {
const [menu, setToggle] = useState(false);
const toggleMenu = () => setToggle(!menu);
return (
<div className={'navbar'}>
<i>Meuartelie</i>
<button className={'hamburger'} onClick={toggleMenu} >☰</button>
<Menu toggle={menu} toggleMenu={toggleMenu}></Menu>
</div>
);
}
Sometimes its inconvenient to extract the component from the render function, for example If the components is dynamically created/determined.
You can then use a the hook useMemo to tell react to store the reference, and only recalulate the value if a prop in the dependency-array changes.
function NavbarAndMenuMemoized() {
const [menu, setToggle] = useState(false);
const toggleMenu = () => setToggle(!menu);
// useMemo will not recalculate Menu each render, instead it will keep the same reference for Menu.
const Menu = useMemo(()=>{
return(props) => (
<div key='1' className={ props.toggle ? `menu__container toggle` : `menu__container` }>
<div className={'menu__content'}>
<ul className={'menu__list'}>
<li className={'menu__item'} onClick={toggleMenu}> <Link href="/"><span>Home</span></Link></li>
<li className={'menu__item'} onClick={toggleMenu}> <Link href="/services"><span>Services</span></Link></li>
<li className={'menu__item'} onClick={toggleMenu}> <Link href="/services#contact"><span>Contact</span></Link></li>
</ul>
</div>
</div>
);
}, [])
return (
<div className={'navbar'}>
<i>Meuartelie</i>
<button className={'hamburger'} onClick={toggleMenu} >☰</button>
<Menu toggle={menu} ></Menu>
</div>
);
}
live demo Example
I am trying to show an edit icon on a cells hover state, using font awesome.
How can make the class name unique so I can target it with css for each row?
import {Icon} from 'react-fa'
if(this.props.day.achievements) {
listItems = this.props.day.achievements.map((achievement) => (
<div className="cell" key={achievement + "_achievements"}>
{achievement}
<div className="edit">
<a href="#">
<Icon name="pencil-square" className="edit" />
</a>
</div>
</div>
))
}
I am using the following css:
.cell:hover .edit {
display: block;
}
.edit {
padding-top: 7px;
padding-right: 7px;
position: absolute;
right: 0;
top: 0;
display: none;
}
.edit a {
color: #000;
}
How can I display the icon for each cell?
Since you're using position:absolute on the edit wrapper, try adding position:relative to the .cell. I suspect your icons ARE showing but they're all floating up to the top overlapping with each other.
I have a JQuery Mobile listview with a custom item height (50px). Whenever the item is clicked, its height changes. How can I fixate the custom height?
Fiddle: http://jsfiddle.net/3gnvhxth/6/
I am using JQuery Mobile v1.45 and JQuery 1.11.1.
Before click:
After click:
HTML:
<ul data-role="listview" data-inset="true">
<li class="custom_item">
<a class="custom_link" href="http://google.com" target="_blank">
<img class="custom_image" src="http://placehold.it/120x120&text=image1">
Click Item 1
</a>
</li>
<a class="custom_link" href="http://google.com" target="_blank">
<img class="custom_image" src="http://placehold.it/120x120&text=image2">
Click Item 2
</a>
</li>
<li class="custom_item">
<a class="custom_link" href="http://google.com" target="_blank">
<img class="custom_image" src="http://placehold.it/120x120&text=image3">
Click Item 3
</a>
</li>
</ul>
CSS:
.custom_item {
height: 50px;
max-height: 50px;
}
.custom_link {
padding-left: 50px !important;
height: 50px;
max-height: 50px;
}
.custom_image {
width: 50px;
height: 50px;
max-width: 50px;
max-height: 50px;
}
Luis is right about the min-height from the jQM CSS file. You need to override it, but also remove top and bottom padding on the link as that causes the height issue on click:
.custom_link {
padding-left: 50px !important;
padding-top: 0;
padding-bottom: 0;
line-height: 50px;
max-height: 50px;
min-height: 0 !important;
height: 50px;
}
Updated FIDDLE
Setting line-height keeps the text vertically centered. If that is not important to you, just remove it.
You have a default min-height in your css that causing the problem
CSS
.ui-listview > .ui-li-has-thumb > .ui-btn, .ui-listview > .ui-li-static.ui-li-has-thumb {
min-height: 3.625em; // Remove this or adjust to your needs
padding-left: 6.25em;
}
<div class="oringal">
<ul class="rank">
<li class="rank-1">
<img src="http://netdna.webdesignerdepot.com/uploads/packaging_design/Tetra_pak_New_packaging_Juice7_by_KATOK.jpg" />
<p>1</p>
</li>
<li class="rank-2">
<img src="http://netdna.webdesignerdepot.com/uploads/packaging_design/21.jpg" />
<p>2</p>
</li>
I want to get the ranking sequence as follows, but i do not want change the html, how can i just change the css in the div.oringal to get the ranking sequence as follows.first in center, second rights, third lefts
please see the full code on jsfiddle page http://jsfiddle.net/6grsm/1/, thanks a lot
You could try using absolute positioning. It looks like you are creating a shopping cart layout so I assume that you have a fairly structured page to start with.
See demo at fiddle: http://jsfiddle.net/audetwebdesign/rC59T/
Your HTML is basically this:
<div calss="panel-wrap">
<ul class="rank">
<li class="rank-1">
<img ... />
<p>1</p>
</li>
<li class="rank-2">
<img ... />
<p>2</p>
</li>
<li class="rank-3">
<img ... />
<p>3</p>
</li>
</ul>
</div>
For the CSS:
.panel-wrap {
width: 460px;
}
The .panel-wrap is useful if you want to add background images and so on.
ul.rank {
list-style: none outside none;
padding: 0;
margin: 0;
position: relative; /* this will force the li to be positioned with respect
to this block level container */
border: 1px solid gray;
height: 200px;
}
ul.rank li {
width: 150px;
top: 0; /* pin top and bottom so that the li fills in the height
of the parent container */
bottom: 0;
border: 1px solid red;
position: absolute;
}
ul.rank img {
width: 150px;
xheight: 90px; /* Careful not to adjust both width and height which could
distort your images */
}
ul.rank p {
border: 1px dotted blue;
text-align:center;
position: absolute;
bottom: 10px;
left: 0; /* pin left and right so the p fills in the
width of the li... */
right: 0;
margin: 0;
}
The trick is to adjust the left offset for each list item in uniformly spaced increments:
.rank-3 {
top: 0;
left: 0;
}
.rank-1 {
top: 0;
left: 160px;
}
.rank-2 {
top: 0;
left: 320px;
}
The Big Advantage
What you could do is set the left offset dynamically using JavaScript/jQuery, and create an interactive page where the user can click buttons and scroll through a series of catalog items.
"i want get the sequence 3 1 2, but i do not want to change the sequence in html in div.original, my question is, how should i change the css"
From that comment, it seems that what you actually is not to change the positioning of elements, but change the order of numbering, which is a completely different question. The easiest way to do this is to use the (deprecated, but still seemingly supported) start attribute of the ol tag. In CSS, you can also set counter-increment for li tags, which will enable customisation of what the li tags display. Examples of the various methods are in this Stackoverflow answer
Basically I'm making a navigation bar and due to Jquery doing a lot of resizing to make a website look 'pretty' I don't want to use a horizontal list and so each button is created like so:
<img src="homeicon.png"><span id="homex"><br /><img src="home.png" /></span>
(yes they're all image buttons for good reason)
but the only problem is they're fixed and set to "top 0" at the top of the page and as a result cannot sit next to each other but rather overlap, any idea on how I can I still keep the position to fixed and they top to 0 yet keep them next to each other?
HTML
<div id="top">
<img src="homeicon.png"><span id="homex"><br /><img src="home.png" /></span>
</div>
CSS
#top a.button { position: fixed; top: 0; padding: 12px; background: url('glacial_ice.jpg'); text-decoration: none; color: black; border-radius: 0px 0px 25px 25px; }
#top { position: relative; top:0; padding-left: 25px; }
Init function (runs on $(document).ready())
$('a.button').animate({
height: '+=5px',
}, 20, function() {
$('a.button').animate({
opacity: 0.6,
height: '-=5px',
}, 20);
});
Thanks
Put them all in a container, i.e. id="header", give the header position:fixed;top:0;etc...
Then, for each of the link/buttons give them:
position:relative;display:inline-block;float:left;
if you want them centered, then in the #header use text-align:center; and remove float:left from the links
So the container will be fixed, but the buttons inside will be relative and not overlap.
hope this helps!
very crude example
http://jsfiddle.net/6SCTZ/
<div id="header">
<div class="button">button1</div>
<div class="button">button2</div>
<div class="button">button3</div>
</div>
CSS:
#header { position:fixed;top:0;width:100%;height:30px;background:black; text-align:center }
.button {position:relative;display:inline-block;color:white;margin:0 5px 0 5px;}
Just put whatever elements need to be fixed within a container element (in this case, I'll use a div with an ID of "top_fixed").
Consider the following html:
<div id='top_fixed'>
<a href='http://google.com'>Google</a>
<a href='http://yahoo.com'>Yahoo</a>
</div>
<div id='tall'></div>
Now, the following CSS:
a { display: inline; }
#top_fixed { position: fixed; top: 0; left: 0; width: auto; }
#tall {height: 2000px; background: #000;}
DEMO: http://jsfiddle.net/mHKNc/1/