Tap highlight on parent element of link, not link itself? - css

Ive used negative margin to make a link larger than its container, and ive hidden the overflow of the parent element. My reasons for doing so are explained in this question:
Responsive navigation - keep links the same height when some wrap?
Here is a working fiddle: http://jsfiddle.net/uwEGj/
The issue is that the tap highlight shows the element being larger than its container. If you use a device like an iPhone on the link above you will see what I mean.
To solve this ive set the link to have this CSS rule:
-webkit-tap-highlight-color: rgba(0,0,0,0);
However I would like a tap highlight over the visible area of the link. I tried to set a tap highlight color to the li e.g. -webkit-tap-highlight-color: rgba(100,100,100,0.6); but it doesnt seem to do anything. See here: http://jsfiddle.net/uwEGj/3/
How can I have a tap highlight colour only over the visible area of the link?

Considering I understand your problem correctly - you are annoyed that the highlighted area overflows a bit over the edge of the link, as on the following image I've got from Google images to illustrate the problem:
AND you want all links to be same height no matter how much text they contain.
First I would correct the markup to fit your table-cell display logic. As you know a table has 3 main elements - table, table-row, table-cell - you are missing the table-row element which makes thing render improperly cross platforms.
I would do the HTML as following:
<div class="link-list">
<div class="link-list-row">
Link 1
Link 2 which has very very very long text and loger
Link 3
</div>
</div>
Than forget about the negative margin (-10em negative margin).
So change the CSS to the following:
.link-list {
display:table;
width:100%;
}
.link-list-row {
display:table-row;
}
a {
display:table-cell;
padding: 10px;
width:33.3%;
heigth:100%;
background: grey;
padding: 10px;
border: 2px solid red;
overflow:hidden;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); /* disable the highlight */
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
box-sizing:border-box;
}
Your highlight is now disabled and your <a> with longer text wraps to next line and also shorter <a> 's will still get same height since they are now displaying as cells.
Now in order to make the highlight as precise as possible you will need some simple javascript to toggle a class on tap events, since the highlight event is system bound.
Most simple solution is using jQuery obviously, but can be accomplished with pure javascript too if you can't use any frameworks.
$('a').on({
'touchstart' : function(){
$(this).addClass('tap');
},
'touchend' : function(){
$(this).removeClass('tap');
}
});
and add a class to your css for the tap event:
a.tap {
background:green;
}
Now you can style your hightlighted state as you wish + the highlight will work on non-webkit browsers also.
Working sample (try on touch enabled device): http://jsfiddle.net/7M6Ey/2/

Related

Expanding the background color rectangle of selected text

According to MDN, outline should work on the ::selection pseudoelement, yet it doesn't seem to when tested on both chrome and ff.
::selection {
background-color:red;
outline:2px dashed blue;
}
My cool text, select me!
I'm creating a text editor and basically it just annoys me how tight fitting the selection background color is. I want to expand it a few pixels and outline would be the right attribute for the job but it doesn't work?
I think the MDN is wrong or not updated, because if we refer to the specification:
The highlight pseudo-elements can only be styled by a limited set of properties that do not affect layout. The following properties apply to the highlight pseudo-elements:
color
background-color
cursor
caret-color
text-decoration and its associated properties
text-shadow
stroke-color, fill-color, and stroke-width
The outline isn't listed which explain why it's not working. Also I don't think you can control the hightlighting area. As explained in the same specification:
For text, the corresponding overlay must cover at least the entire em box and may extend further above/below the em box to the line box edges. Spacing between two characters may also be part of the overlay area, in which case it belongs to the innermost element that contains both characters and is selected when both characters are selected.
We already have the em box which is trivial and your best luck is to have more in case the line box is higher but it will not behave the same cross browser.
Here is a basic example where I use a pseudo element with a big font-size to increase the height of the line-box and I align it in the middle. In this case the selection will cover more than the text but of course this will also affect the layout which is probably not needed and will not work with all the browser.
The below example works on Chrome and doesn't on Fiferfox
p:after {
content: "";
font-size: 30px;
vertical-align: middle;
}
p::selection {
background-color: red;
}
<p>My cool text, select me!</p>
Another important thing is that all the properties applied inside that area cannot overflow it. We know that with text-shadow we can place the shadow far from the text but with the selection it won't be possible because it cannot overflow the hightlighting area:
p {
text-shadow:0 10px 0 red;
}
p::selection {
background-color: red;
text-shadow:0 -10px 0 blue;
}
<p>My cool text, select me!</p>
Notice how the blue text-shadow is partially visible like we have applied overflow:hidden to the red area. So even if you are able to style the selection with outline it's basically impossible to control its dimension which is what you need here.
I think your best option is to rely on JS to create dynamic element or wrap selected text to easily style them. With the CSS, you can only apply some hack that will affect your layout.
Outside the first line, the other line is valid with line-height. As you can see:
div {
line-height:30px;
}
div::selection {
background: yellow;
}
<div>text<br />text<br />text</div>
So, I did a Javascript trick that added the first line for us. I'm also giving font-size: 0px for the first line. So our problem is solved. As you can see:
let a = document.querySelectorAll(".a");
a.forEach(function(par){
par.insertAdjacentHTML('afterbegin','needed text<br />')
})
// for an unseen first line.
.a {
line-height:50px;
}
.a::selection {
background: yellow;
}
.a::first-line {
font-size:0px;
line-height:0px;
}
<div class="a">text</div>

Chrome and Firefox overflow:hidden jumping elements

I stumbled over a strange behaviour that occurs in Chrome and Firefox when you have got an element with "position:relative;" and "overflow:hidden;" and an anchor in it with "position:absolute;".
Whenever the anchor gets focus the element above it magically jumps to the top, even though its styles and markup tell a different story.
Example: http://codepen.io/mediadivisiongmbh/pen/pJWmxp
All you need is a setup similar to this:
HTML
<div class="container">
<h1>I can fly</h1>
<a class="focus-me" href="#">Evil Link</a>
</div>
CSS
.container {
position:relative;
overflow:hidden;
/* Optional */
border:1px solid gray;
}
.focus-me {
position:absolute;
}
Thanks for your answers so far. In order to clarify the issue please take a look at this example:
http://codepen.io/mediadivisiongmbh/pen/bdRjKy
When you hover over the container, the absolute positioned element containing the anchor will transition in view. When you click on it a lightbox (in this case Magnific Popup) is opened. After you close this lightbox the anchor gets focus again and jumps into view, which looks pretty odd.
Setting the anchor to display:none by default and display:block when hovering over the container worked for solving this issue.
After more research I figured out that the problem is caused by an accessibility feature in chrome.
In my case I just needed to make sure the anchor tag is only accessible while hovering over the container element.
Therefore the solution was altering the CSS like this:
.container {
position:relative;
overflow:hidden;
/* Optional */
border:1px solid gray;
}
.focus-me {
position:absolute;
display:none;
}
.container:hover .focus-me {
display:inline-block;
}
I'm not pretty clear about what you're looking for since you have different story. But if you mean you want to prevent jump because of focus on your link, you can use tabindex="-1" on your link to makes it not accepting tab stop. Check the Updated Pen
EDIT
Well when seeing your pen, I think you need to set display: none to your evil link and set it to display: inline-block when hovering to your container. Check Updated Pen.

Try to align a span and an input

I have two buttons, one implemented as an input, the other as a span. They are put side by side with:
{ display:inline-block; }
The buttons are rendered from a customized tag and a class name is added dynamically in jsp. In css, there are some definition for shadow, for background gradient, for padding, and for font. They do use some CSS3 like border-radius.
But in Firefox, the height of the span button is 18 while the input 20. Interestingly, the height of them in IE 8 are both 25px, why?
Now I need them to be of the same height and aligned horizontally.
Update:
Now I have those two buttons in jsfiddle. Use height:22px; and vertical-align:top; won't help much.
http://jsfiddle.net/gBeCP/
Try setting the vertical-align:top on the input tag. I recommend specifically setting the dimensions in px as this will prevent the browser from applying defaults.
I think I have it done.
Answer in this page indicates that FF treats the padding differently in submit type of input and a span. CSS padding added to height/width for <input type='submit'>
My solution is to set a min-height of both input and span, then use vertical-align:middle; to have them aligned. Finally play around the padding number to have the text on the buttons aligned.
The reason it's different is because each browser has its own default styles so they will vary... just like javascript varies dramatically.
Have you ever thought about actually setting some height on the elements that you want to be the same height?
maybe
span, input[type="button"] {
height: 25px;
}
Or more specifically if you like.
The easiest solution is the following two lines (vendor-prefixes removed for brevity):
.tranCoreButton {
/* I couldn't be bothered to read through the rest of the CSS, or the
in-line CSS; seriously: *minimal* reproductive demo, please... */
display: inline-block;
box-sizing: border-box;
}
JS Fiddle demo.

CSS: last child element's height should be based on previos siblings but not overflow parent

Relevant JS Fiddle http://jsfiddle.net/arosen/FMQtR/
Problem
My HTML looks something like this:
<div id='parent'>
<div id='one'>
A variable amount of text here.
</div>
<div id='two'>
A less important variable amount of text here.
</div>
</div>
The #parent div is a fixed height and cannot change. Within it, I have at least two child divs. The first one (or many) will have an unknown amount of text in it determining its height. Based on the content of the first one, I want the last one to take up as much height is left in the parent but not overflow.
My current example CSS is:
#parent {
border: 1px solid #000;
height: 150px;
width: 150px;
}
#one, #two {
border: 1px dashed #333;
height: auto;
margin: 5px;
padding: 5px;
overflow: hidden;
}
My current JS solution
function() {
var $two = $('#two');
var $parent = $('#two').parent()
$parent.css('overflow', 'hidden');
var heightDifference = $parent[0].scrollHeight - $parent.height();
$two.css('height', $two.height() - heightDifference);
}
I'm wondering if there is a CSS layout or HTML solution to this problem or if I must use the JS solution I have in the fiddle that is run on the push of the last button.
EDIT Updated my JS fiddle as the text will not change once on the page but depending on information loaded from the server, will not know how much text it will have until the page is rendered.
EDIT 2 Only modern (and IE 9) browsers need to be supported.
EDIT 3 The final div must have a height as it is used by other jQuery plugins.
No. You can't. CSS isn't a programming language. Instead every selector{ property:value; } tuple defines a rule for a specific set of elements. The actual style such as current height, current width or other properties cannot be accessed in CSS.
Someone might think "what about percentage values"? Well, those are based on the containing block, which is often the parent element (in this case #parent).
So you either have to specify a fixed height for all div (which isn't possible according to the information you gave us), or use a JavaScript based solution.
You could accomplish this if you're not too set on borders/margin/padding/line-height. Just make sure that (parent div - (all margins/padding)) is wholly divisible by your line-height, you'd never see partial lines or overflow. However, with your border styles you can't achieve this through CSS alone.
You could still hack it by adding another element to the parent div, say a paragraph tag with the dashed border-top, and a thick white bottom border, positioned to hide the overflowing border with the above solution... but that's hacky, which I'm not a fan of, and has a potential to break easily across browsers.
TL;DR - Just use your JS.

iScroll prevents my div from showing (when implementing div slider)

I'm trying to implement a div slider into a standard iScroll HTML page, please see the below links:
With iScroll (slide not working properly):
http://utvecklingspunkten.se/iscroll.html
Without iScroll (slide working):
http://utvecklingspunkten.se/iscroll2.html
For some reason, iScroll hides the content (not the div containing it!) in the second div slide. The div containing the content is there allright and it's corretly possitioned (have a look in the console), but the content is simply hidden by iScroll. When removing all references to iScroll, as in iscroll2.html, everything works as it should.
Wrapper containing both slides:
#wrapper {
position:absolute; z-index:1;
top:45px; bottom:2px; left:0;
background:#aaa;
-webkit-transition-property: left;
-webkit-transition-duration: 400ms;
display:block !important;
}
Each sliding element:
.additional-block {
position: absolute;
display:block !important;
}
Does anyone know how I can make iScroll and the slider to work together, and not interfere? Hopefully, there's only a line of code or two in iscroll.js that need to be changed. Likewise, an iScroll div (like the artificial scrollbar) overlaping my second slide div is another possible reason. Pointing this out for me would be greatly appreciated. Thanks!
Try using jQuery Slider, you can style it inside out. Plus you have there already mouse dragging and scrolling ( which actually works ).

Resources