Issue with the direction: rtl CSS property - javascript

I have an HTML element and I need to display a folder / file path within it that can sometimes be very long.
I also want to keep it on a single line (within a width constrained container) so I obviously need to add some ellipsis to it.
Another requirement is that I should always see the deepest folder nodes in that path (this is helpful when the path is long, because the latest nodes is what you're actually interested in).
The problem is, this is quite hard to achieve if I'm to use the direction: rtl; CSS property, because it will move other characters around, such as / or even paranthesis.
Take a look at this example: https://jsfiddle.net/r897duu9/1/ (as you can see, I didn't use the text-overflow: ellipsis property as this will, for some reason, override the direction: rtl property).
What I've tried so far and it works on modern browsers is adding the unicode-bidi: plaintext; CSS property, but according to the Mozilla Developer Network this is experimental and not well supported across not-so-modern cough IE browsers. The fiddle for this is here: https://jsfiddle.net/n05b3jgt/1/ .
Does anyone know a better way to achieve this, that would be well supported across a wide range of browsers?

I looked at the other solutions but I think this is simpler and more effective.
.title-wrapper {
max-width: 200px;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
direction: rtl;
}
.title {
unicode-bidi: plaintext;
}
<div class="title-wrapper">
<span class="title">asdasd/qweqwe/xcvxcv/rtyrty/dfgdfgdfgdfgdfgd</span>
</div>

You may use direction on container then reset it on text.
.container {
width: 340px;
background:gray;
direction:rtl;
overflow:hidden;
text-align:left;
position:relative;
}
.container:before{
position: absolute;
content: '...';
background: white;
left: 0;
}
.text-with-path {
display:inline-block;
white-space:nowrap;
text-indent:1em;
direction:ltr;
<div class="container">
<div class="text-with-path">
/Root/someFolder/SomeAnotherFolder/AgainSomeotherFolder/MyPictures/MyDocs (recent)
</div>
</div>
<hr/>
<div class="container">
<div class="text-with-path">
/MyPictures/MyDocs (recent)
</div>
</div>
or just use float if your main issue is which way text overflows
.container {
width: 340px;
background:gray;
overflow:hidden;
position:relative;
}
.container:before{
position: absolute;
background:gray;
content: '...';
left: 0;
}
.text-with-path {
float:right;
margin-left:-999px;
}
<div class="container">
<div class="text-with-path">
/Root/someFolder/SomeAnotherFolder/AgainSomeotherFolder/MyPictures/MyDocs (recent)
</div>
</div>

Related

How can I adjust my bootstrap based css code so it is more responsive to the page width?

I created this fiddle as you can see there I have a webpage with two texts, one below another. It works great on wide screens, but when I shrink the webpage - or run the webpage on mobile - it is messed up, like on this screenshot:
I thought about doing it more responsive by adding CSS mobile queries, but then in the code I have:
#media (max-width: 545px) {
.outer{
width:100%;
height:330px;
top:0;
position:relative;
}
.inner1{
width:100%;
height:320px;
margin-bottom:0px;
}
.inner2{
width:100%;
height:330px;
margin-bottom:0px;
}
}
#media (max-width: 435px) {
.outer{
width:100%;
height:380px;
top:0;
position:relative;
}
.inner1{
width:100%;
height:370px;
margin-bottom:0px;
}
.inner2{
width:100%;
height:380px;
margin-bottom:0px;
}
}
#media (max-width: 378px) {
.outer{
width:100%;
height:460px;
top:0;
position:relative;
}
.inner1{
width:100%;
height:450px;
margin-bottom:0px;
}
.inner2{
width:100%;
height:460px;
margin-bottom:0px;
}
}
etc., so lot's of values for different screen widths. I suspect there's some other way of doing that, the most responsive way in which I don't need to cover each screen width separately in mobile CSS...
Can you give me any hint how could I change my code so it works independently on any device/screen width?
Thanks!
Set minimum width and height for each class so that the page stops adjusting the text with screen resolutions that are too small. Add min-height:123px; and min width:456px; (adjust px as needed) so that they do not overlap on small screens.
Note: This isn't very good for mobile.
In your fiddle you are setting the height of each div (inner1 and inner2), and when you compress the page width to about 150px (you picture) the divs are overflowing. Setting the height of an elements is not done often, at least from my experience. On mobile platforms width is usually more of a concern.
Setting the overflow attribute inside your css for each div fixed the issue for me.
.inner1{
width:100%;
height:270px;
margin-bottom:0px;
overflow: auto;
}
.inner2{
width:100%;
height:280px;
margin-bottom:0px;
overflow: auto;
}
Here is a reference for the overflow property. Using auto at least allows for scrolling and wont cut off the text.
https://developer.mozilla.org/en-US/docs/Web/CSS/overflow
Bootstrap actually has a grid system made for the exact purpose of making the width values responsive to screen size.
http://v4-alpha.getbootstrap.com/layout/grid/
Also, setting the viewport width for mobile phones will load the css to run at the actual screen width of the phone, rather than the pixel density width of the screen: https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag
The problem you run into is caused by the content of .inner1 becoming too high and showing up in your .inner2. The .inner1 is able to become too high because of their overflow. It shows your text even past the height you specified. To stop this behavior apply
.inner1{
overflow:hidden;
}
That said, I cannot recommend using the method you have been using to make the content appear/disappear (with a fixed height). I would personally use display:none and remove display:none by code (and possible animation) in this scenario. But that is beyond the question asked, so I won't go into that.
JSFiddle
HTML (with bootstrap)
<div class= "container">
<div class="row">
<div class="col-sm-7 company">
<h2>this is my title</h2>
<div class="companyDescription" >
<div class="outer">
<div class="inner1" id="inner1">
<h5>"The quick brown fox jumps over the lazy dog" is an English-language pangram—a phrase that contains all of the letters of the alphabet. It is commonly used for touch-typing practice. It is also used to test typewriters and computer keyboards, show fonts, and other applications involving all of the letters in the English alphabet
</h5><h5>Some kind of subtitle</h5>
<h5><a id="readMore" style="cursor: pointer; cursor: hand;">read more...</a></h5>
</div>
<div class="inner2">
<h5><a id="readLess" style="cursor: pointer; cursor: hand;">...read less</a></h5>
<h5>As the use of typewriters grew in the late 19th century, the phrase began appearing in typing and stenography lesson books as a practice sentence. Early examples of publications which used the phrase include Illustrative Shorthand by Linda Bronson (1888), How to Become Expert in Typewriting: A Complete Instructor Designed Especially for the Remington Typewriter (1890)
</h5>
<h5>the last subtitle.</h5>
</div>
</div>
</div>
</div>
</div>
</div>
CSS
.company {
padding-top: 160px;
color: #000;
}
.companyDescription {
margin: 20px 0 10px 0;
overflow:hidden;
}
.outer{
width:100%;
height:280px;
top:0;
position:relative;
}
.inner1{
width:100%;
height:270px;
margin-bottom:0px;
overflow:hidden;/*ONLY ONE NEW CSS LINE!*/
}
.inner2{
width:100%;
height:280px;
margin-bottom:0px;
}
Javascript (with jQuery)
$('#readMore').click(function(){
$('.companyDescription').animate({
scrollTop:$('#inner1').outerHeight()+30
}, 1000);
})
$('#readLess').click(function(){
$('.companyDescription').animate({
scrollTop:0
}, 1000);
})
Here is my code you can also go through below link -
JSFiddle
HTML Code -
<div class="col-md-12">
<div class="row">
<div class="col-md-12 company">
<h2>this is my title</h2>
<div class="companyDescription">
<div class="outer">
<div class="inner1" id="inner1">
<h5>"The quick brown fox jumps over the lazy dog" is an English-language pangram—a phrase that contains all of the letters of the alphabet. It is commonly used for touch-typing practice. It is also used to test typewriters and computer keyboards, show fonts, and other applications involving all of the letters in the English alphabet
</h5>
<h5>Some kind of subtitle</h5>
<h5><a id="readMore" style="cursor: pointer; cursor: hand;">read more...</a></h5>
</div>
<div class="inner2">
<h5 style="display:none;"><a id="readLess" style="cursor: pointer; cursor: hand;">...read less</a></h5>
<h5 style="display:none;">As the use of typewriters grew in the late 19th century, the phrase began appearing in typing and stenography lesson books as a practice sentence. Early examples of publications which used the phrase include Illustrative Shorthand by Linda Bronson (1888), How to Become Expert in Typewriting: A Complete Instructor Designed Especially for the Remington Typewriter (1890)
</h5>
<h5 style="display:none;">the last subtitle.</h5>
</div>
</div>
</div>
</div>
</div>
</div>
JAVASCRIPT Code -
$('#readMore').click(function() {
$('#readMore').css('display','none');
$('.inner2').find('h5').css('display','block');
})
$('#readLess').click(function() {
$('#readMore').css('display','block');
$('.inner2').find('h5').css('display','none');
})
Bootstrap already provide the best responsive design. But still if you want to add more responsiveness you can add your own classes with the html tags and then use media queries for specific width.
<div class="container class1">
content here
</div>
<ul class="list-item class2">
<li> list item </li>
</ul>
now you have to apply your css on your given classes which in this case are class1 and class2
Thanks
We got 2 choices,
1. Set a large static height...
Change the statically set width to a large number like say 250px which will work well for low res... but will have too much of (ugly) white space on desktop.
.inner1{
width:100%;
height:250px;
margin-bottom:0px;
overflow: auto;
}
.inner2{
width:100%;
height:250px;
margin-bottom:0px;
overflow: auto;
}
2. Calculate height dynamically on resize...
This work work for all resolutions with just as much whitespace as desired on all resolutions ;)
For this
First wrap the contents in .inner1 and .inner2 in a container, we used article here... this will help us determine the height of content.
Now Set height to 100% for .inner1 and .inner2...
.inner1 {
width: 100%;
height: 100%; /* Set height as 100% */
margin-bottom: 0px;
}
.inner2 {
width: 100%;
height: 100%; /* Set height as 100% */
margin-bottom: 0px;
}
Then give .outer a default height, like maybe 160px
.outer {
width: 100%;
height: 160px;
top: 0;
position: relative;
}
Finally some JS to make it work ;)
Update
We use a function assigned to a var instead of using an anonymous function.
On resizing window, we check the heights of content in inner1 and inner2, use the one with more content using Math.max then add 25px gutter to it and set it as .outer height...
var fixWidths = function() {
var
$cDesc = $('.companyDescription');
$cDesc.find('.outer').css(
'height',
Math.max(
$cDesc.find('.inner1').children('article').outerHeight(),
$cDesc.find('.inner2').children('article').outerHeight()
) + 25 // Maximum of the two
)
}
$(window).resize(fixWidths);
fixWidths();
Update
Make sure your JS code is wrapped in...
$(function() {
...
});
This will wait until doc is loaded...
At the end we trigger resize programmatically, to set the correct initial state.
A working example
$(function() {
$('#readMore').click(function() {
$('.companyDescription').animate({
scrollTop: $('#inner1').outerHeight() + 30
}, 1000);
})
$('#readLess').click(function() {
$('.companyDescription').animate({
scrollTop: 0
}, 1000);
})
var fixWidths = function() {
var
$cDesc = $('.companyDescription');
$cDesc.find('.outer').css(
'height',
Math.max(
$cDesc.find('.inner1').children('article').outerHeight(),
$cDesc.find('.inner2').children('article').outerHeight()
) + 25 // Maximum of the two
)
}
$(window).resize(fixWidths);
fixWidths();
});
.company {
padding-top: 160px;
color: #000;
}
.companyDescription {
margin: 20px 0 10px 0;
overflow: hidden;
}
.outer {
width: 100%;
height: 160px;
top: 0;
position: relative;
}
.inner1 {
width: 100%;
height: 100%;
/* Set height as 100% */
margin-bottom: 0px;
}
.inner2 {
width: 100%;
height: 100%;
/* Set height as 100% */
margin-bottom: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-sm-7 company">
<h2>this is my title</h2>
<div class="companyDescription">
<div class="outer">
<div class="inner1" id="inner1">
<article>
<h5>"The quick brown fox jumps over the lazy dog" is an English-language pangram—a phrase that contains all of the letters of the alphabet. It is commonly used for touch-typing practice. It is also used to test typewriters and computer keyboards, show fonts, and other applications involving all of the letters in the English alphabet
</h5>
<h5>Some kind of subtitle</h5>
<h5><a id="readMore" style="cursor: pointer; cursor: hand;">read more...</a></h5>
</article>
</div>
<div class="inner2">
<article>
<h5><a id="readLess" style="cursor: pointer; cursor: hand;">...read less</a></h5>
<h5>As the use of typewriters grew in the late 19th century, the phrase began appearing in typing and stenography lesson books as a practice sentence. Early examples of publications which used the phrase include Illustrative Shorthand by Linda Bronson (1888), How to Become Expert in Typewriting: A Complete Instructor Designed Especially for the Remington Typewriter (1890)
</h5>
<h5>the last subtitle.</h5>
</article>
</div>
</div>
</div>
</div>
</div>
</div>
Here's the updated fiddle...
https://jsfiddle.net/2nexo75j/16/
You can use clearfix class
<div class="clearfix"></div>
Did you included "jquery-ui-1.10.4.min.js" file? and is order of all css js files are correct?
Because same code of yours with the same styling and scripting working for me.Try this bellow code.
<!DOCTYPE html>
<html>
<head>
<title>Scroll</title>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" type="text/css">
<script>
$(document).ready(function () {
$('#readMore').click(function () {
$('.companyDescription').animate({
scrollTop: $('#inner1').outerHeight() + 30
}, 1000);
});
$('#readLess').click(function () {
$('.companyDescription').animate({
scrollTop: 0
}, 1000);
});
});
</script>
<style>
.company {
padding-top: 160px;
color: #000;
}
.companyDescription {
margin: 20px 0 10px 0;
overflow:hidden;
}
.outer{
width:100%;
height:280px;
top:0;
position:relative;
}
.inner1{
width:100%;
height:270px;
margin-bottom:0px;
}
.inner2{
width:100%;
height:280px;
margin-bottom:0px;
}
</style>
</head>
<body>
<div class= "container">
<div class="row">
<div class="col-sm-7 company">
<h2>this is my title</h2>
<div class="companyDescription" >
<div class="outer">
<div class="inner1" id="inner1">
<h5>"The quick brown fox jumps over the lazy dog" is an English-language pangram—a phrase that contains all of the letters of the alphabet. It is commonly used for touch-typing practice. It is also used to test typewriters and computer keyboards, show fonts, and other applications involving all of the letters in the English alphabet
</h5><h5>Some kind of subtitle</h5>
<h5><a id="readMore" style="cursor: pointer; cursor: hand;">read more...</a></h5>
</div>
<div class="inner2">
<h5><a id="readLess" style="cursor: pointer; cursor: hand;">...read less</a></h5>
<h5>As the use of typewriters grew in the late 19th century, the phrase began appearing in typing and stenography lesson books as a practice sentence. Early examples of publications which used the phrase include Illustrative Shorthand by Linda Bronson (1888), How to Become Expert in Typewriting: A Complete Instructor Designed Especially for the Remington Typewriter (1890)
</h5>
<h5>the last subtitle.</h5>
</div>
</div>
</div>
</div>
</div>
</div>
</body>

How do I make a <hr /> tag go vertically

How do I make a <hr /> tag go vertically, instead of its standard appearance as a horizontal line/going sideways?
I'd like to be able to use this on a mobile site, so a more widely-supported solution is preferable to one that only works in the latest browsers.
This will require changes to more than just the hr. the element above and below it must be floated. the effect can be achieved with a solid border:
<div class="section1"> content </div>
<div class="section2"> more content </div>
CSS:
.section1 {
float: left;
width: 200px;
border-right: 1px solid #333;
}
.section2 {
float: left;
width: 200px;
}
Edit: see also this answer
You could use css transforms. However, this just turns it, things are still where they would be if you hadn't rotated it.
HTML
<hr/>
<hr class="vert" />
<hr id="vert1" />
CSS
/*All <hr>*/
hr {
transform:rotate(90deg);
-ms-transform:rotate(90deg);
/* IE 9 */
-webkit-transform:rotate(90deg);
/* Safari and Chrome */
}
/*<hr> of class ".vert"*/
hr.vert {
transform:rotate(90deg);
-ms-transform:rotate(90deg);
-webkit-transform:rotate(90deg);
}
/*<hr> with id "vert1"*/
hr#vert1 {
transform:rotate(90deg);
-ms-transform:rotate(90deg);
-webkit-transform:rotate(90deg);
}
Well you could possibly make a div (<div></div>) and then give it values with css later regarding height/width. If you want it to apply to one specific object give it an id <div id=""> and more than one object give it a class <div class="">
An example of the css you'd do is:
#(id name) or div.(class name) {
height: ; (how tall)
width: ; (how wide you want it)
background-color: ; (sets the color of the bar)
position: ; (depends on if you want it absolute or static etc.) }
You can obviously add/remove other css as you go depending on what you want to do
Put it in a div:
<div style="border-right:1px solid #333;">
Content here
</div>
This is with inline css. Otherwise, separate the css:
div {
border-right:1px solid #333;
}
I suppose you could re-style <hr /> as an inline-block element, with specified height...
hr {
display: inline-block;
width: 2px;
height: 256px;
}
That's just a basic example to get the <hr /> to look like I think you want it to look. You'd have to play with height and width (and possibly positioning) to make it do exactly what you need...

half transparent div above image

I have a PNG image of a character, and I want something like that:
http://www.swfcabin.com/open/1364482220.
If someone clicks on a part of the character's body, it'll be "selected".
The question is - how can I do that. I don't want to use more images (because I have multiple characters), I want to use CSS only.
I tried this: http://jsfiddle.net/eRVpL/, but the green background appear above the white background, and I want it to be only above the character.
The code:
<div class="character">
<img src="http://img194.imageshack.us/img194/3854/goldgladiator.png" />
<span></span>
</div>
<style>
.character { width: 210px;display: inline-block; vertical-align: middle; position: relative; }
.character > span {
display: block;
width: 200px;
height: 30%;
background: rgb(160, 255, 97);
opacity: .3;
position: absolute;
top: 0;
}
img {
max-width: 200px;
}
</style>
You can make this work with CSS masks, although they are currently only supported in WebKit browsers: http://caniuse.com/#feat=css-masks
http://jsfiddle.net/eRVpL/3/
HTML:
<div class="character">
<img src="http://img194.imageshack.us/img194/3854/goldgladiator.png">
<div class="green-mask"></div>
</div>
CSS:
.green-mask {
height: 200px;
width: 508px;
background: rgb(160, 255, 97);
opacity: .3;
position: absolute;
top: 0;
-webkit-mask-image: url(http://img194.imageshack.us/img194/3854/goldgladiator.png);
}
If you want to offset the elements like in the GIF you linked, put the colored background on children of the masked div:
http://jsfiddle.net/eRVpL/11/
HTML:
<div class="character">
<img src="http://img194.imageshack.us/img194/3854/goldgladiator.png">
<div class="green-mask">
<div class="filler"></div>
</div>
</div>
CSS:
.filler {
background-color: rgba(160, 255, 97, 0.3);
height: 200px;
margin-top: 200px;
width: 100%;
}
.green-mask {
position: absolute;
width: 508px;
top: 0;
-webkit-mask-image: url(http://img194.imageshack.us/img194/3854/goldgladiator.png);
}
And this one's just for fun: http://jsfiddle.net/eRVpL/23/ Try clicking the character. It uses checkboxes and labels with no JavaScript.
Currently there is no CSS-only means of accomplishing this. There is a specification for compositing and blending with CSS that's in the works, but it currently isn't being supported enough to be used in a product just yet. You can read-up on the spec here: http://www.w3.org/TR/compositing/
With this specification, we could set the blend-mode of your element to "screen", "overlay", or "lighten" which would make your character be green but the background would remain white. Unfortunately, this isn't possible just yet.
The best way would be, as jcubic said in one of your comments, "You need to use a mask, image that will be exactly the same but the character transparent".
Good luck!
Try using z-index for getting what you want. You'll be able to make the object appear to be hidden on a certain page until you bring it up with a mouse click or hover. You can also make a green image that's basically a silhouette and cut it up into three different portions, give them a little bit of exact positioning (each with their own division) and have a little z-index, then you've got yourself that. You might also want to cut up the actual character into three parts to make it easier.

Add dots/ellipsis on div/span element overflow without using jquery

Need to implement functionality similar to what dotdotdot jQuery plugin does
but cannot use javascript frameworks (like jquery or ext).
Is there any easy way to add the dots to the content of div or span element if content takes more space then element should???
(similar to what css overflow: ellipsis setting does)
Can't use ellipsis beacause it doesn't work with many lines when height is limited.
Thank you :)
Why not using the CSS property text-overflow? It works great as long as you define a width in your tag.
Class in CSS:
.clipped {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
<div class="clipped" style="width: 100px;" title="This is a long text">This is a long text<div>
You can also add the text to the title attribute, so the user can see the whole text when hovering over the element.
Works for any number of lines and any width without any javascript - and is responsive. Simply set your max-height to a multiple of your line height: i.e. (22px line height) * (max 3 lines of text) = (max height 66px).
https://codepen.io/freer4/pen/prKLPy
html, body, p { margin: 0; padding: 0; font-family: sans-serif;line-height:22px;}
.ellipsis{
overflow:hidden;
margin-bottom:1em;
position:relative;
}
.ellipsis:before {
content: "\02026";
position: absolute;
bottom: 0;
right:0;
width: 1.8em;
height:22px;
margin-left: -1.8em;
padding-right: 5px;
text-align: right;
background-size: 100% 100%;
background: linear-gradient(to right, rgba(255, 255, 255, 0), white 40%, white);
z-index:2;
}
.ellipsis::after{
content:"";
position:relative;
display:block;
float:right;
background:#FFF;
width:3em;
height:22px;
margin-top:-22px;
z-index:3;
}
/*For testing*/
.ellipsis{
max-width:500px;
text-align:justify;
}
.ellipsis-3{
max-height:66px;
}
.ellipsis-5{
max-height:110px;
}
<div class="ellipsis ellipsis-3">
<p>Here we can have a great many lines of text and it works as we expect it to. Here we can have a great many lines of text and it works as we expect it to. Here we can have a great many lines of text and it works as we expect it to. Here we can have a great many lines of text and it works as we expect it to.</p>
</div>
<div class="ellipsis ellipsis-5">
<p>The number of lines shown is easily controlled by setting the max-height of the .ellipsis element. The downsides are the requirement of a wrapping element, and that if the text is precisely as long as your number of lines, you'll get a white area covering the very trailing end of your text. You've been warned. This is just some pushing text to make the element longer. See the ellipsis? Yay.</p>
</div>
You could try:
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
This will only work if your elements are not dynamically sized. They will have to have a width set or some other mechanism to keep them from growing to allow more content.
My solution to my problem can seem a little awkward, but it works for me:)
I used a little of CSS:
word-wrap: break-word;
and Javascript:
var spans = document.getElementsByTagName("span");
for (var i in spans) {
var span = spans[i];
if (/*some condition to filter spans*/) { // just
if (navigator.appName == 'Microsoft Internet Explorer') {
span.parentNode.style.display ='inline-block';
}
if (span.parentNode.clientHeight > 50 ) {
span.innerHTML = span.innerHTML.substr(0, 26) + ' ...';
}
}
}
FOR ALL Browser:
.dotdot{ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; max-width:80px}
.dotdot:before { content: '';}
<div class="dotdot">[Button Text Goes here][1]</div>

Position badge over corner of image automatically

I have a layout where images "float" within a certain area. The layout looks like this:
The source like this:
<div class="free_tile">
<a class="img_container canonical" href="/photos/10">
<img class="canonical" src="http://s3.amazonaws.com/t4e-development/photos/1/10/andrew_burleson_10_tile.jpg?1303238025" alt="Andrew_burleson_10_tile">
<!-- EDIT: I am aware that I can put the badge here. See the edit notes and image below. -->
</a>
<div class="location">Houston</div>
<div class="taxonomy"> T6 | Conduit | Infrastructure </div>
</div>
The CSS looks like this (in SCSS):
div.free_tile { width: 176px; height: 206px; float: left; margin: 0 20px 20px 0; position: relative;
&.last { margin: 0 0 20px 0; }
a.img_container { display: block; width: 176px; height: 158px; text-align: center; line-height: 156px; margin-bottom: 10px; }
img { margin: 0; border: 1px solid $dark3; display: inline-block; vertical-align: middle; #include boxShadow;
&.canonical { border: 1px solid $transect; }
}
.location, .taxonomy { width: 176px; }
.location { font-weight: 700; }
.taxonomy { line-height: 10px; font-size: 10px; text-transform: uppercase; height: 20px; overflow: hidden; }
}
div.transect_badge { height: 20px; width: 20px; background: url('/images/transect-badge.png'); }
So, basically the images are sitting vertically-aligned middle and text-aligned center, and they have a maximum width of 176 and max height of 158, but they're cropped to maintain the original aspect ratio so the actual top corner of each image falls differently depending on which image it is.
I have a badge that I'd like to put in the top corner of certain images (when the image is "canonical"). You see the style for this above (div.transect_badge).
The problem, of course, is I don't know where the top corner of the image will be so I can't hardcode the position via CSS.
I assume that I'll need to do this via jQuery or something. So, I started with a jQuery method to automatically append the badge div to any canonical images. That works fine, but I can't figure out how to position it over the top left corner.
How can this be done? (ideally using just HTML and CSS, but realistically using JS/jQuery)
--EDIT--
Here's the problem: The image is floating inside a container, so the corner of the image might fall anywhere inside the outer limits of the container. Here's an example of what happens if I try to use position:absolute; top:0; left:0 inside the same container the image is bound by:
It took some tryouts, but here it is: the size independent image badge positioner.
HTML:
<div class="tile">
<span class="photo">
<img src="/photos/10.jpg" alt="10" /><ins></ins>
</span>
<p class="location">Houston</p>
<p class="taxonomy">T6 | Conduit | Infrastructure</p>
</div>
CSS:
.tile {
float: left;
width: 176px;
height: 206px;
margin: 0 20px 20px 0;
}
.photo {
display: block;
width: 176px;
height: 158px;
text-align: center;
line-height: 158px;
margin-bottom: 10px;
}
a {
display: inline-block;
position: relative;
line-height: 0;
}
img {
border: none;
vertical-align: middle;
}
ins {
background: url('/images/badge.png') no-repeat 0 0;
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
}
Example:
In previous less successful attempts (see edit history), the problem was getting the image vertically centered ánd to get its parent the same size (in order to position the badge in the top-left of that parent). As inline element that parent doesn't care about the height of its contents and thus remains to small, but as block element it stretches to hís parent's size and thus got to high, see demonstration fiddle. The trick seems to be to give that parent a very small line-height (e.g. 0) and display it as an inline-block. That way the parent will grow according to its childs.
Tested in Opera 11, Chrome 11, IE8, IE9, FF4 and Safari 5 with all DTD's. IE7 fails, but a center-top alignment of the photo with badge at the right position isn't that bad at all. Works also for IE7 now because I deleted the spaces in the markup within the a tag. Haha, how weird!
EDIT3: This solution is very similar to my original solution. I didn't really look at your code much so I should have noticed this earlier. Your a tag is already wrapping each image so you can just add the badge in there and position it absolute. The a tag doesn't need width/height. Also you must add the badge image at the beginning of your a tag.
Demo: http://jsfiddle.net/wdm954/czxj2/1/
div.free_tile {
width: 176px;
height: 206px;
float: left;
}
a.img_container {
display: block;
margin-bottom: 10px;
}
span.transect_badge {
display:block;
position: absolute;
height: 20px;
width: 20px;
background-image: url('/images/transect-badge.png');
}
HTML...
<a class="img_container canonical" href="/photos/10">
<span class="transect_badge"></span>
<img class="canonical" src="path/to/img" />
</a>
Other solutions...
In my code I'm using SPAN tags so simulate images, but it's the same idea. The badge image, when positioned absolute, will create the desired effect.
Demo: http://jsfiddle.net/wdm954/62faE/
EDIT: In the case that you need jQuery to position. This should work (where .box is your container and .corner is the badge image)...
$('.box').each(function() {
$(this).find('.corner')
.css('margin-top', ( $(this).width() - $(this).find('.img').width() ) / 2);
$(this).find('.corner')
.css('margin-left', ( $(this).height() - $(this).find('.img').height() ) / 2);
});
EDIT2: Another solution would be to wrap each image with a new container. You would have to move the code that you use to center each image to the class of the new wrapping container.
Demo: http://jsfiddle.net/wdm954/62faE/1/
$('.img').wrap('<span class="imgwrap" />');
$('.imgwrap').prepend('<span class="badge" />');
Technically you can just add something like this to your HTML though without using jQuery to insert it.
Use an element other than <div>, e.g. <span> and put it inside your <a> element after the <img> element. Then, give the <a> element position:relative; and the <span> gets position:absolute; top:0px; left:0px;. That is, if you don't mind the badge also being part of the same link - but it's the easiest way. Also, the reason for using <span> is to keep your HTML4 valid, <div> would still be HTML5 valid, however.
I did find one solution using jQuery. I don't prefer this because it noticably impacts page loading, but it is acceptable if nothing else will work. I'm more interested in NGLN's idea which seems promising but I haven't entirely figured out yet. However, since this thread has picked up a lot of traffic I thought I'd post one solution that I came up with for future readers to consider:
Given this markup:
<div class="free_tile">
<a class="img_container canonical" href="/photos/10">
<img class="canonical" src="http://s3.amazonaws.com/t4e-development/photos/1/10/andrew_burleson_10_tile.jpg?1303238025" alt="Andrew_burleson_10_tile">
<span class="transect-badge"></span>
</a>
<div class="location">Houston</div>
<div class="taxonomy"> T6 | Conduit | Infrastructure </div>
</div>
Same CSS as in question except:
span.transect-badge { display: block; height: 20px; width: 20px; position: absolute; background: url('/images/transect-badge.png'); }
Then this jQuery solves the problem:
$(function() {
$('img.canonical').load( function() {
var position = $(this).position();
$(this).next().css({ 'top': position.top+1, 'left': position.left+1 });
});
});
Like I said, though, this incurs noticeable run-time on the client end, so I'd prefer to use a non JS solution if I can. I'll continue to leave this question open while I test out and give feedback on the other solutions offered, with hopes of finding one of them workable without JS.

Categories

Resources