css/javascript for element positioning / sizing - javascript

I am after some general pointers on how to go about the following.
I am trying to position some elements (divs) in a web page by absolute position, relative to the element in which they live.
The idea being that the containing element top/left should be exactly where it would be in the normal document flow, the width should be set such that it fills <body> up to the RHS, less a small margin, and height such that it fills the remainder of the display window, less the space taken up by a footer (also a div).
Having done that, I can then absolutely position sub-elements inside it. The problem is setting the width/height of the containing element.
I have tried various combination of position properties and javascript executed onload(), without success. I clearly am not taking the right approach.
What I am really after are some pointers from someone who knows how to do this as to the approach to be taken. The bottom line is that I need that containing element to expand to be as big as it can, given the constraints of the browser window and the space taken by the footer element.
.... More info following comments.
Basically, I am trying to display a schedule, not unlike a TV/radio schedule. I.e. a line per event class, then within each line lots of individual events displayed in boxes, with the 'box width/position' scaled to the start/end of the actual event on a timeline.
I've seen this done simply using HTML tables and lots of columns to get
the necessary granularity, then using colspan to vary the widths. However I thought I'd try to do it with absolute positioning of elements. The first problem being that the containing element then has no idea how big this thing is, because using position:absolute takes each element out of the document flow. Therefore, no scroll bars either, even with overflow-x:auto on the containing element.
I am getting nowhere fast with css/javascript (well, certainly nowhere, but not even very fast, actually), and I am starting to wonder of the only real way to control the UI closely is by writing a java applet to contain it all?
Hence my question: conceptually, what would be a good way of going about this?

for the container to contain an absolute element, the height must be set to a fixed height or dynamically set the height using Javascript.
See Example https://codepen.io/jacobgoh101/pen/kkWJaL
HTML
<div class="container">
<img src="https://s21.postimg.org/c1m6ky7dz/kingston_creative_market_cover_small_f.jpg">
</div>
CSS
.container {
position: relative;
width: 90%;
border: 1px solid #000;
}
.container > img {
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
Javascript with jQuery
window.onload = function() {
var imgHeight = $('.container img').height();
var targetHeight = imgHeight * 1.2;
$('.container').height(targetHeight);
};

Related

How to position Recaptcha V2 challenge popup in the center of the viewport?

My Recaptcha challenge popup overflows the viewport on mobile and I'm also unable to scroll the page.
I need to always show challenge popup in the center of the viewport (horizontally and vertically). I've looked at Recaptcha API and didn't found how to execute code after challenge popup was rendered. It's rendered with Explicit not automatically.
I've tried:
To change the first parent of the iframe CSS class by adding code after .render function, but the iframe was null.
I tried to detect the click on the Recaptcha checkbox inside iframe in a recursive function (nonblocking loop) and then to change the popup CSS class, but the checkbox is always null, until I go with the chrome inspector to the checkbox, then trying to get the checkbox in the console works.
ReCaptcha v2 causes the issue on smaller (mobile) screens. I managed to work around the issue using CSS.
First scales down the recaptcha container (g-recaptcha in some examples) to take less screen space (optional).
#recaptcha-container
{
transform: scale(0.77);
-webkit-transform: scale(0.77);
transform-origin: 0 0;
-webkit-transform-origin: 0 0;
}
Hide the bubble arrow pointing from the checkbox to the challenge bubble (also optional, but looks nicer IMHO).
.g-recaptcha-bubble-arrow
{
display: none;
}
I believe you're looking for something like the following to find the bubble arrow's sibling div element which contains the iFrame with the challenge and center it on the screen (whatever the size is).
.g-recaptcha-bubble-arrow + div
{
position: fixed !important;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
}
Note that I'm using CSS transform, so check the browser support for your target browser and version. Also note that this works for the current implementation of ReCaptcha, if the HTML output changes in the future a different solution may be necessary.

Position fixed within container element instead of the browser / viewport

I need to position a header to be fixed within the containing parent so that it follows when scrolling. The problem is that
position:fixed
fixes the position to the browser, not the parent. What this is resulting in is that when I have a container that has a horizontal scroll for overflow in the width (the content is wider than the container), my fixed header does not have the overflow-scroll as the content of the table does.
See this fiddle demo
So the goal here is to fix the position of the header, but fixed relative to it's parent container. In this fiddle, you can see that I've commented out a block of css:
.container{
/*-webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);*/
-webkit-transform: none;
-moz-transform: none;
-ms-transform: none;
transform: none;
}
If you replace the current css block (with transform set to none) with the one with translateZ, the header will get positioned within it's parent container, but is no longer fixed.
Anyone know how to solve this? Preferred solution would be CSS/HTML only and avoid JS but if nothing else, then JS is of course what I need to go with!
CSS can't do this by itself.
Position: fixed works in relation to the viewport, not it's containing element.
I've seen an attempt to solve this problem using the CSS3 transform property, but (as you noted in your comment to my first answer) it doesn't seem to work.
I understand you can't use any client-side library but that's the only solution available to my knowledge. For you and others who may one day need this, here's a solution that works. It employs a bit of jQuery:
Positioning an element inside another element with the positioned element fixed along the x and y axes (i.e. position fixed horizontally and vertically).
http://jsfiddle.net/8086p69z/8/
HTML
<div class="moving-article">
<div class="container">
<header class="fixed-header">FIXED HEADER</header>
<ul>
<li>SCROLL</li>
<li>SCROLL</li>
<li>SCROLL</li>
</ul>
</div>
</div>
CSS (relevant section)
.moving-article {
height: 150px;
width: 75%;
overflow-x: scroll;
}
.fixed-header {
background: rgba(0,0,0,0.5);
width: 50%;
text-align: center;
line-height: 40px;
position: absolute;
top: 0;
left: 0;
}
.container{
width: 1000px;
}
jQuery
var leftOffset = parseInt($(".fixed-header").css('left'));
$(window).scroll(function(){
$('.fixed-header').css({
'left': $(this).scrollLeft() + leftOffset
});
});
set the header's position to 'absolute', and it's parent container (which you want it to be relative to) to 'relative', and set it to stick to the top of the parent with 'top: 0'
CSS:
.container {
position: relative;
}
.child {
position: absolute;
top: 0;
}
To keep an element fixed within a parent cannot be done with position: fixed because position: fixed takes the element out of the flow and therefore it has no parent. It positions itself relative to the viewport.
To accomplish your goal, while keeping things simple and efficient, you may want to consider Tether, "a client-side library to make absolutely positioned elements attach to elements in the page efficiently".
Hope this helps. Good luck.

CSS3 translate out of screen

For a number of projects now I have had elements on the page which I want to translate out of the screen area (have them fly out of the document). In proper code this should be possible just by adding a class to the relevant element after which the css would handle the rest. The problem lies in the fact that if for example
.block.hide{
-webkit-transform:translateY(-10000px);
}
is used the element will first of all fly out of the screen unnecessarily far and with an unnecessarily high speed. And purely from an aesthetic point of view there's a lot left to be desired (Theoretically speaking for example a screen with a height of 10000px could be introduced one day in the future).
(Update) The problem why percentages can't be used is that 100% is relative to the element itself, rather than to the parent element/screen size. And containing the element in a full-sized parent would be possible, but would create a mess with click events. And after a few answers, allow me to point out that I am talking about translations, not about position:absolute css3 transitions (which are all fine, but once you get enough of them they stop being fun).
What aesthetically pleasing solutions to allow an element to translate out of a screen in a fixed amount of time can you guys think of?
Example code can be found in this jsfiddle demonstrating the basic concept.
http://jsfiddle.net/ATcpw/
(see my own answer below for a bit more information)
If you wrap the .block div with a container:
<div class="container">
<div class="block"></div>
</div>
<button>Click</button>
you could expand and then, translate the container itself after the click event
document.querySelector("button").addEventListener("click", function () {
document.querySelector(".container").classList.add("hide");
});
with this style
.block {
position:absolute;
bottom:10px;
right:10px;
left:10px;
height:100px;
background:gray;
}
.container {
-webkit-transition: -webkit-transform ease-in-out 1s;
-webkit-transform-origin: top;
-webkit-transition-delay: 0.1s; /* Needed to calculate the vertical area to shift with translateY */
}
.container.hide {
position:absolute;
top:0;
left:0;
bottom:0;
right:0;
/* background:#f00; /* Uncomment to see the affected area */
-webkit-transform: translateY(-110%);
}
In this way, it is possible to apply a correct translationY percentage ( a little more than 100%, just to have it out of the way ) and mantaining the button clickable.
You could see a working example here : http://jsfiddle.net/MG7bK/
P.S: I noticed that the transition delay is needed only for the transitionY property, otherwise the animation would fail, probably because it tries to start before having an actual value for the height. It could be omitted if you use the horizontal disappearing, with translateX.
What I did is use the vh (view height) unit. It's always relative to the screen size, not the element itself:
/* moves the element one screen height down */
translateY(calc(100vh))
So if you know the position of the element in the screen (say top:320px), you can move it exactly off the screen:
/* moves the element down exactly off the bottom of the screen */
translateY(calc(100vh - 320px))
I know this is not exactly what you were asking but...
Would you consider using CSS animations with Greensock's Animation Platform? It is terribly fast (it claims it's 20 times faster than jQuery), you can see the speed test here: http://www.greensock.com/js/speed.html
It would make your code nicer I believe, and instead of trying to hack CSS animations you could focus on more important stuff.
I have created a JSFiddle here: http://jsfiddle.net/ATcpw/4/
Both CSS and possible JS look simpler:
document.querySelector("button").addEventListener("click",function(){
var toAnimate = document.querySelector(".block");
TweenMax.to(toAnimate, 2, {y: -window.innerHeight});
});
CSS:
.block{
position:absolute;
bottom:10px;
right:10px;
left:10px;
height:100px;
background-image: url(http://lorempixel.com/800/100);
}
I recently built an app which used precisely this technique for sliding 'panels' (or pages) and tabs of the application in and out of view. A basic implementation of the tabs mechanism can be seen here.
Basically (pesudo-code to illustrate the concept, minus prefixes etc):
.page {
transform: translateY(100%);
}
.page.active {
transform: translateY(0%);
}
The problem I had was that Android Webkit in particular wouldn't calculate percentage values correctly. In the end I had to use script to grab the viewport width and specify the value in pixels, then write the rules using a library for dynamic stylesheet parsing.
But eventually, and in spite of only these minor platform-specific problems, this worked perfectly for me.
Use calc method (http://jsfiddle.net/ATcpw/2/):
.block{
position:absolute;
top: -webkit-calc(100% - 110px);
right:10px;
left:10px;
height:100px;
background:gray;
-webkit-transition: all 2s;
/*this adds GPU acceleration*/
transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);
}
.block.hide{
top: -100px;
}
Since you are using -webkit prefix I used it as well.
calc is supported by majority of browsers: http://caniuse.com/#search=calc
One very simple, but not aesthetically pleasing solution is to define the class dynamically:
var stylesheet = document.styleSheets[0];
var ruleBlockHide;
and
//onresize
if(ruleBlockHide) stylesheet.deleteRule(ruleBlockHide);
ruleBlockHide = stylesheet.insertRule('.block.hide{ -webkit-transform:translateY(-'+window.innerHeight+'px); }',stylesheet.cssRules.length);
see: http://jsfiddle.net/PDU7T/
The reason a reference to the rule needs to be kept is that after each screen resize the rule has to be deleted and re-added.
Although this solution gets the job done, there has to be some DOM/CSS combination which would allow this to be done without javascript (something along the lines of a 100%x100% element containing such a block, but I haven't been able to figure out any transform based way).
get the document width. then use a java script trigger to trigger the css3 translation.
function translate(){
var width = document.body.Width;
document.getElementById('whateverdiv').style='translateX(' + width + 'px)';
}
This is simple
add the following to your div
.myDiv {
-webkit-transition-property: left;
-webkit-transition-duration: 0.5s;
-webkit-transition-timing-function: ease-in-out;
-webkit-transition-delay: initial
}
then change the "left" property of it either by adding an additional class or by jQuery
This will animate it along the x-axis
Note: you can change the -webkit-transition-property to any property you want and this will animate it

Applying CSS3 Transformations based on Window Width and Height

My web application is using some of the css3 transformations and I was wondering the best way to do these based on the window's width and height. My css is doing multiple transformations and in a specific sequence, i.e the body does one, and an element on the body does a second after the transformation the body did. However, one of my transformations is hardcoded to move the element X pixels which I want to make dynamic based off the window's height and width.
Is there a way without javascript (I'd need to preserve the order of these transformations) to say something like:
.someClass {
transform:translate(windowHeight /2, windowHeight);
}
transform: translate may not be your best bet. I'd try position: fixed and use a window percentage value:
position: fixed;
top: 50%;
left: 50%;
One can use viewport based units. For instance:
transform: translate(50vw, 50vh);

Center AnythingSlider with hidden overflow on both sides

My goal is to have the slider 1280px wide and centered on the page. I would like the edges of the content to have hidden overflow on both sides. For example I want the center of content to always stay in the center of the page with each side being cut off as the browser is resized, with no horizontal scroll bar appearing.
Is there a straightforward way to accomplish this?
I ended up with a somewhat interesting solution that worked for me in (at least) Chrome, Firefox, and Safari where I tested it. It may be slightly hacky, but the result was cool.
So here's what I did: I put a .wrapper with a width of 1280px. The margin is 0 auto except the left margin which is where it all happens. The left margin needs to be set to half of the div width. In this case that would be 640px. However, because it must overflow outside of the left screen it must be set to a negative number (i.e. -640px). Then in order to reverse that effect when the screen is larger then screen a left:50% pushed it over the correct amount. Obviously in order for the margin:0 auto to actually work, the position must be set to relative (or absolute if you would like).
.wrapper { width:1280px;
margin:0 auto 0 -640px;
position:relative;
left:50%
}
the one problem
I found one problem with it, though. Because we are using negative margin, it pushes the div to the left to where one can not see if their screen or browser window is too small. Let me know if this is a problem and makes it to where it doesn't work for you.
Add this css class
.overflowbothsides{
vertical-align: middle;
margin: 0 auto;
position: relative;
left: 50%;
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-o-transform: translateX(-50%);
transform: translateX(-50%);
}
solution with code and example
enter link description here

Categories