Aligning images with variable length text - html

What would be the best way to accomplish something like this, but where the icons are vertically-aligned with the middle of the text (which has variable length)?
The icons are CSS sprites, with the background moving over 26px when hovering on the icon or associated text

New answer compatible with CSS sprites
In response to #Octavian's feedback, here's a different way of dealing with the issue that still allows the use of CSS sprites. The solution here is to use display:table on the li and display:table-cell on its children, in order to vertical align them. Then, instead of an image, a placeholder div with a background-image can be used for the sprites. Here's a jsFiddle, and the code is below:
CSS
ul {padding-left:0;}
li {display:table;margin-bottom:20px;}
.image-holder {
display:table-cell;
width:26px;
height:26px;
vertical-align:middle;
background-image:url('http://placehold.it/52x26');
background-repeat:no-repeat;
background-position:left center;
}
li:hover .image-holder {background-position:right center;}
.text {padding-left:30px;display:table-cell;}
HTML
<ul>
<li>
<div class="image-holder"></div>
<span class="text" style="display:table-cell;">www.website.com</span>
</li>
<li>
<div class="image-holder"></div>
<span class="text" style="display:table-cell;">742 Evergreen Terrace<br/>Springfield, SP 12345<br/>United States</span>
</li>
<li>
<div class="image-holder"></div>
<span class="text" style="display:table-cell;">T) (800) 555-5555<br/>F) (800) 666-6666</span>
</li>
</ul>
Old answer, more elegant but incompatible with sprites
Another option would be to use each image as a background-image positioned in the top middle of each li. The key piece of CSS here is background-position, the first argument of which represents the horizontal alignment (top in this case) and the second argument of which indicates vertical alignment (center in this case). Documentation here. Here's a jsFiddle, and the code is below:
CSS
li {
background-position:left center;
background-repeat:no-repeat;
padding-left:40px;
padding:5px 0 5px 60px;
margin-bottom:20px;
list-style-type:none;
background-image:url('http://placehold.it/30x30');
}
HTML
<ul>
<li id="website">www.website.com</li>
<li id="address">742 Evergreen Terrace<br/>Springfield, SP 12345</li>
<li id="phone">T) (800) 555-5555<br/>F) (800) 666-6666</li>
<li id="email">info#website.com</li>
<li id="share">Share via email</li>
</ul>
Edit 1 In response to #cimmanon's comment (thanks!) example now works with images larger than text, and I've posted an accompanying demo.
Edit 2 Altered in line with #Octavian's comment indicating a need for middle-aligning rather than top-aligning.
Edit 3 New answer compatible with CSS sprites

You want to set the line-height to the height of the image (or 50% for double lines)

Related

Trouble getting the right CSS selector

I'm having trouble getting the right selector.
Let me try to explain the best way I can:
I'm working on a project that I cannot change HTML and Javascript, it has some dynamic HTML and other reasons.
On the project, there is an image on a <img> tag.
However, I need to change colors between two layouts, and as you can see on the HTML/CSS the only way I got that to work is to hide th <img> tag and set a background to the anchor, that has a title.
So, now, when I change the layouts, the image changes, however there is also something else, this image on click hides the menu and changes the image one more time.
Now, I need to hide the background on the anchor when the title on the image changes.
Here is the HTML BEFORE clicking the image
<div id="div-mh-ico">
<ul id="ul-icone-mh" class="icones">
<li>
<a href="#" class="mh-icon" title="Esconder menu horizontal" onclick="hideMenuHorizontal();">
<img title="Esconder menu horizontal" id="imgHideMenu" src="images/ico_hidemh.png" width="16" height="16">
</a>
</li>
</ul>
And here is the HTML AFTER I click on the image
<div id="div-mh-ico">
<ul id="ul-icone-mh" class="icones">
<li>
<a href="#" class="mh-icon" title="Esconder menu horizontal" onclick="hideMenuHorizontal();">
<img title="Exibir menu horizontal" id="imgHideMenu" src="images/ico_showmh.png" width="16" height="16">
</a>
</li>
</ul>
THE CSS
I HIDE THE ORIGINAL IMAGE, USED ON THE OTHER LAYOUT
#ul-icone-mh li a img {
visibility: hidden !important;
}
AND SET THE NEW IMAGE
a[title="Esconder menu horizontal"] {
box-sizing: border-box;
background-image: url(../images/ico_hidemhc.png);
background-size: 16px;
background-repeat: no-repeat;
}
And when I click it, the image stays the same, but I need to hide that image when the title changes and add another image.
Any ideas what I can do?
You need a bit more than just the right CSS selector. The problem there is the old stumbling block that there is no parent selector.
A bit more thought and work is required.
img { height:50px; width:50px }
ul {padding: 0; list-style:none;}
.icones a::after {
content: '';
height:50px; width:100px;
background-image: linear-gradient(to right, #00FF00 50%, #0000FF 50%);
display:inline-block;
}
.icones a {
height:50px; width:50px;
display:block;
white-space:nowrap;
overflow:hidden;
font-size:0;
}
.icones a img[title='Esconder menu horizontal'] {
margin-left: -50px;
}
.icones a img[title='Exibir menu horizontal'] {
margin-left: -100px;
}
<div id="div-mh-ico">
<ul id="ul-icone-mh" class="icones">
<li>
<a href="#" class="mh-icon" title="Esconder menu horizontal" onclick="hideMenuHorizontal();">
<img title="Esconder menu horizontal" id="imgHideMenu" src="http://placehold.it/200/ff0000" width="16" height="16">
</a>
</li>
</ul>
</div>
<div id="div-mh-ico">
<ul id="ul-icone-mh" class="icones">
<li>
<a href="#" class="mh-icon" title="Esconder menu horizontal" onclick="hideMenuHorizontal();">
<img title="Exibir menu horizontal" id="imgHideMenu" src="http://placehold.it/200/990000" width="16" height="16">
</a>
</li>
</ul>
</div>
Here I've increased the images to 50x50px from 16x16px to make them a bit easier to see but the principle is just the same.
For the two images referenced by the HTML, I've used two blocks that are different shades of red.
For the two CSS overlay images, for simplicity I've used a linear gradient making a block that's the height of the image and twice the width. The left half is green and the right half blue. You would use a sprite for the two images you want to display. The left half of the sprite would contain the "Esconder ..." replacement image and the right half of the sprite would contain the "Exibir ..." replacement image.
I've also shown both cases together rather than switching between them on click, again for simplicity.
The idea is that the left margin of the image is made negative to shift it out of the a element. The pseudo element that follows contains the sprite and is shifted into that space, either by the width of the image, or twice the width of the image to show different contents for the two cases.
Hence we get a green box for the "Esconder ..." case and a blue box for the "Exibir ..." case.
So if I understand correctly, then the title is "esconder", you want to hide the default image and inject your own. And otherwise you want to show the original (when the title is "exibir".)
You have correctly identified how you would target the a tag based on the title: a[title="Esconder menu horizontal"]. What you then need to do is only exclude the image when it is inside of this tag, and then replace it with your own image. You then also need to give it an explicit size, and declare the a tag which now directly has the background image with some size. Like so:
a[title="Esconder menu horizontal"] img { display: none; }
a[title="Esconder menu horizontal"] {
box-sizing: border-box;
background-image: url(../images/ico_hidemhc.png);
background-size: 16px;
background-repeat: no-repeat;
height: 16px;
width: 16px;
display:inline-block;
}
You will notice I added a few lines to your existing styling:
display:inline-block tells the browser that this element should follow the flow like an inline element, but should have block-type semantics. By default, an anchor tag is an inline element, which means it doesn't have explicit size or width -- just what is enforced by its children. Since you've delcared that the child is not to be seen, the anchor tag effectively collapses to be of 0x0 size.
height:16px; width:16px tells the browser the size you want for this image. I guessed at these dimensions based on the background-size property you had set. Since we've told the browser using the display property that this element has explicit size, we now tell it what that size is.
It's not very clear what you're trying to accomplish, but if you're trying to change the anchor based on the image, this is simply not possible using CSS alone.
You can target child elements based on their parents, but you can not target parent elements based on their children in CSS (currently).
The only way to do this would be to affect how the HTML renders the two options, or using Javascript.
There are a few different suggested specs for such a selector, but none have yet been implemented.
Since the img tag is what has the dynamic title, that is the only thing you will be able to target with your CSS. If you cannot accomplish your task by targeting the img then it can't be done within the constraints you stated.
Selectors:
https://www.w3.org/TR/CSS2/selector.html
Support for the proposed spec for a parent selector:
https://caniuse.com/#feat=css-has

absolute positioning is driving me nuts

can any body explain me the out put, which my code is genrating, as it
driving me nuts, there is no syntax error, i am following the tutorial
on you tube and i was able to genrate the right out put with this
code, but today i decided that i will understood this code fully, and
it driving me crazy
**Note: No syntax error, just looking for explanation about the out put, and please read the comment in the code
First look at the code html**
<html>
<head>
<title>TODO supply a title</title>
<link rel="stylesheet" href="menu.css"></link>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<label for="show-menu" class="show-menu">Show Menu</label>
<input type="checkbox" id="show-menu" >
<ul id="menu">
<li >Home</li>
//This section is giving me trouble, please see below i explain my problem in detail there
<li >about
<ul class="hidden">
<li >who are we</li>
<li >what we do</li>
</ul>
</li>
//This section is giving me trouble, please see below i explain my problem in detail there.
<li >portfolio
<ul class="hidden">
<li >photography</li>
<li >web & interface design</li>
<li >illustration</li>
</ul>
</li>
<li >news</li>
<li >contacts</li>
</ul>
</body>
</html>
and this is my css
/*strip styling from the list*/
ul{
margin:0;
padding:0;
list-style-type:none;
position:absolute;
}
li{
display:inline-block;
float:left;
margin-right:1px;
}
//only this section of the code is driving me crazy, and in the explanation i type this section again and again. Please see below in there i explain my problem in detail.
li a {
display:block;
}
Problem if you look at the out put in this link
https://codepen.io/arif_suhail_123/pen/pwdYXp
i am confused about this-- look at the about section, i was expecting who we are and what we do, to appear as block element, as i gave li a {display:block} but they dont, they are appearing as inline block element or inline element, i am not sure,
but i get more confused when i see the next portion portfolio, as in there, all the li are appearing as block element, means photography, web & interface design and illustration appear on the next line, which i was accepting, after giving this style li a {display:block}
and after that i completly lost my mind when i added min-width property,
see the link https://codepen.io/arif_suhail_123/pen/ZyaZEj i changed nothing, i only added in li a {} min-width, so my style is this li a {display:block; min-width:140px;}
i still have the problem, what we do appear under the portfolio, this problem i desribed already(in the last paragraph), but after adding min-width:140px; i have new problem; if you look at the out put, web & interface design appear under the news, first of all i did not expected it to appear there, and second of all if you read the html code web & interface design is second li means why it appearing in this order first li -- photography, than third li -- illustration and second li -- web & design, under the news??
Can any body please explain me,
and last of all, what i understand about the absolute positioning is this, that it take the element out of normal flow, and put it back at the given position, i ran one example, and it confirm what i think may be i am wrong but have look https://codepen.io/arif_suhail_123/pen/LLOaXv
on this link third box did not appear, as i was expecting it, not to appear,
and about the block element, i understand that they suppose to appear on the new line.
see these two picture i think my question will become more clear.
Absolute Positioning - Take the Width of Parent
Ok so I looked through your code and I made a small example out of it. I took out some things to make the example more clear (and because of width limitations in these posts).
Ok, first, look at the background colors I put on both of the <ul> lists. Your sub-lists are in red. Your main <ul> is in yellow.
Now you are correct in saying that position: absolute; takes the element out of the "flow" of other elements in order to display them as usual. Absolute positioning takes a lot of special attention.
Run the code and look at the words "Who are we". Now this makes you think, why does "photograpy" appear next to it? What happened to "what we do"? Its behind it. The reason this occurs is because both of those lists are positioned absolutely under their parent element. Without giving anything like top or left they are just going to overlap eachother and the latter ends up displaying ontop of the previous list. Absolutely positioned elements don't care what is next to them or if they overlap something. They go where ever you tell them to and thats typically what absolute positioning is for. You tell it to break away from normal flow, and you give it a specific location to appear.
Play around with the code, delete "photography" and "illustration" and run it again. You'll see that "what we do" was there all along, just behind it.
Also see Russell's Answer.
ul{
margin:0;
padding:0;
list-style-type:none;
position:absolute;
background-color: yellow;
}
ul ul{
display: block;
padding: 5px;
background-color: red;
}
#secondList{
background-color: pink;
}
ul li{
float:left;
margin: 5px;
width: 120px;
}
ul ul li a{
display: block;
}
<ul id="menu">
<li>Home</li>
<li>about
<ul class="hidden">
<li>who are we</li>
<li>what we do</li>
</ul>
</li>
<li >portfolio
<ul class="hidden" id="secondList">
<li>photography</li>
<li>illustration</li>
</ul>
</li>
<li>news</li>
</ul>
i am confused about this-- look at the about section, i was expecting who we are and what we do, to appear as block element, as i gave li a {display:block} but they dont, they are appearing as inline block element or inline element, i am not sure,
They do appear as block elements. I think the 'problem' is that you have li declared as inline-block elements. So you have block elements in a container set to inline block which effectively makes them display as inline-block.
but i get more confused when i see the next portion portfolio, as in there, all the li are appearing as block element, means photography, web & interface design and illustration appear on the next line, which i was accepting, after giving this style
This is being displayed the same, but the pen you entered has some kind of arbitrary width assigned to it. I'm not sure if it's because of the viewport settings or not, but try shortening some of the link names and you'll see it's actually displaying them the same as the other list. IE inline-block just like was specified.
Can any body please explain me, and last of all, what i understand about the absolute positioning is this, that it take the element out of normal flow, and put it back at the given position
Absolute positioning takes the element out of normal flow and positions it relative to it first positioned parent. The browser does not set aside space for the element either.
https://developer.mozilla.org/en-US/docs/Web/CSS/position
I'm not 100% sure if I understood the problem but I'll give it a shot:
position: absolute;
makes the element ignore every single element. That is what makes them on top of each others. It just displays whereever you tell it to display. Wich is in the top left corner by default. And that's also why there is an
z-index: ...;
the z-index indicates wich layer the element is displayed on, for example z-index: -10; makes it on layer -10 and an element with z-index -9 would display on top I think(pretty sure, otherwise its the opposite) there are infinite layers btw
Hope this is what you were looking for

Making a picture associated with a list a link

Hi I have a unordered list where I have a section where theres a list as seen in this code
<li id = "project"> My Projects </li>
Where the id project corresponds too
#project
{
list-style-image:url(link.png);
position:relative;
left:20px;
top:100px;
}
Im wondering on how I can make this link.png clickable. I have found an example where you click a picture and it goes into a link, but im kind of confused what to do here since this is inside of an unordered list ( I dont know any Javascript by the way, just recently started relearning html and css)
The question is WHY would you make only a LI bullet clickable?
Think about a better use experience. Bigger clickable area = total happiness.
Set a left padding to the inner anchors,
Set an equal negative left margin to cover the custom bullet image
#menu li{
position:relative;
}
#menu li a{
display:block;
background:rgba(255,0,0, 0.1); /* demo: to make visible the clickable area */
padding-left:45px;
margin-left:-45px;
}
#li_videos {list-style-image:url(//placehold.it/30x30/af8);}
#li_project {list-style-image:url(//placehold.it/30x30/f0f);}
<ul id="menu">
<li id="li_videos">Videos</li>
<li id="li_project">Projects</li>
</ul>
If you want only your list icon clickable you could do:
<li>
<!-- move me till I overlay the icon list image -->
My Projects
</li>
than using CSS give the li a anchor a size and move it till it overlays completely your list-style-image.

Two different font sizes one line css

How can I style one line of text in u nav bar with two different font sizes??
In my html I have:
<nav>
<ul>
<li><a heref="#">Home</a></li>
<li><a heref="#">About</a></li>
<li><a heref="#">Products</a></li>
<li><a heref="#">Stockists</a></li>
<li><a heref="#">Blog <em>(a pinch of psalt)</em></a></li>
<li><a heref="#">Contact</a></li>
</ul>
</nav>
Where I have
<li><a heref="#">Blog <em>(a pinch of psalt)</em></a></li>
I want Blog to be 35px and (a pinch of psalt) to be say 15px. I have used child selectors to target each of the nav elements to style for colour, font size etc but am unsure of how to target two separate elements on this one line in my css.
Just .nav ul li a and .nav ul li a em . If this is what you are looking for
Add a <span> to your HTML and give it a class which will allow you to target it with CSS. For example:
<li><a heref="#"><span class="big">Blog</span> <em>(a pinch of psalt)</em></a></li>
And CSS:
nav li .big {
font-size: 35px;
}
You already have an <em> tag around the remaining text (or you can target nav li a with a "default" text size), so that's the only HTML you will need to add. Just keep in mind that you should be consistent.
On another note.
Answer to my google search for other non situations.
The below CSS class definition
font.yellow {
color:yellow
}
works seamlessly when used like:
<p class"blue">
blue text here
<font class="yellow">yellow text</font>
still blue text here
</p>

How to make floating divs fill up space

I'm trying to create a "workflow" bar on a web page.
The items in the workflow might be of different lengths.
There might be enough items to fill the width of the screen, hence the flow needs to wrap onto the next line.
I'm using left floating divs to do this.
However, I'd like the divs to take an appropriate amount of screen width.
If only three items can fit on one line, then I'd like those items to fit evenly on the line, taking into account each individual items width.
All I can get at the moment is for the final div on a line to fill up the remaining space, which often means my items are all left aligned, e.g. I can get a layout like this:
AAAA -> BBBBB ->
CCCCCCCCCCCCCCCCCCC -> DD -> EEE ->
FFFFF -> GGGG -> HHHHH
but I actually want it to look something like this:
AAAA -> BBBBB ->
CCCCCCCCCCCCCCCCCCC -> DD -> EEE ->
FFFFF -> GGGG -> HHHHH
if you see what I mean.
Do I need to use tables for this rather than floating divs?
just a couple of other pointers. You should not have empty li tags, that is not semantically correct. Also in an ideal world you should not give id attributes layout names.
Personally I'd place the starting image on the ul and then place the closing image on the last li.
could probably do with seeing the surrounding markup to understand what elements you have in place. You could try having a surrounding div with margin: 0 auto;
You're probably going to need a surrounding div for each level.
Don't waste your time just go here:
http://www.cssmenubuilder.com/build-breadcrumb-menu
Thanks for the prompt responses. I'll try out what you are suggesting.
I'm currently trying to do this using a list, although I also got nowhere with divs.
I've tried pulling some HTML of my JSPs in order to try and demonstrate where I'm up to with this.
The spans have a class of "navigation" which basically draws a background image around the text to make it look like a button, as well as setting margins/paddings/etc. I've omitted the CSS which is directly related to the button drawing, since this is standard framework stuff in our system to draw a button. I have included the CSS which I'm using which is directly related to the workflow.
I'm trying to draw a starting image before the first button and then draw background images behind each button in order to draw a line between each button to represent the flow. I've then got an ending image at the end of the flow.
<html>
<body>
<STYLE>
#nav, #nav ul {
list-style: none;
margin: 0px;
width: 700px;
}
#nav li {
list-style: none;
float: left;
padding-left: 10px;
padding-right: 10px;
width: auto;
background-image: url(/lookandfeel/images/navMenuDiv.gif);
background-repeat: repeat-x;
}
li#ending {
background-image: url(/lookandfeel/images/navMenuRight.gif);
background-repeat: no-repeat;
}
li#start {
background-image: url(/lookandfeel/images/navMenuLeft.gif);
background-repeat: no-repeat;
}
.navigation a {
background-image: url(/pdr/images/navigation.gif);
}
</STYLE>
<ul id="nav" style="width: 100%;border: 1px solid">
<li id="start" />
<LI >
<SPAN class="navigation" >AAAAAAAAAA</SPAN>
</li>
<LI >
<SPAN class=navigation >BBBB</SPAN>
</li>
<LI >
<SPAN class=navigation>CCCCCCCCCCCCCCCCC</SPAN>
</li>
<LI>
<SPAN class=navigation>DDDDDDDDD</SPAN>
</li>
<LI>
<SPAN class=navigation>EEEEEEEE</SPAN>
</li>
<LI>
<SPAN class=navigation>FFFFFFFFFFFFFF</SPAN>
</li>
<li>
<SPAN class=navigation>GGGGGGGGGGGGGGGGGGGGGGGGGGGGG</SPAN
</LI>
<li id="ending" />
</ul>
</body>
</html>
Setting the li elements to display: inline, and giving the ul a text-align: justify property will get you part way there (in FFX3 and IE7 at least). However, it does raise some complications when applying the background images.
As much as I dislike to say things can't be done, I think I have to agree with #johnners on the surrounding element for each navigation level. Even if you were to use table layout CSS you would need some sort of surrounding element for each 'row' in order to get the spacing on the left and right correct.