How to calculate the distance to the parent element in CSS? - css

When I have an element in a flexbox parent element, is there a way to get the distance to the parent element left/top boundary?
I would like to use a CSS animation to distribute the objects from 0,0 to their actual positions like this
#keyframes distribute_elements {
from {
translateX(calc(distance_to_parent_left));
translateY(calc(distance_to_parent_top));
}
to {
/* nothing special */
}
}

CSS isn't an actual programming language. You can't gather data using CSS. Javascript and jQuery are your only two options for the task you're trying to accomplish. You could also take the two numbers and calculate it yourself...
Javascript:
var child = document.getElementById('insertChildElementID').offsetTop;
var parent = document.getElementById('insertParentElementID').offsetTop;
var distance = child - parent;`
JQuery:
var child = $('#insertChildElementID').position.top;
var parent = $('#insertParentElementID').position.top;
var distance = child - parent;
For a better jQyuery explanation go to this website.
For a better Javascript explanation go to this website.

Related

Angular / CSS style change width of row items

I am conceiving a horizontal bar containing items.
They must all be of same width, having the same spacing between them.
They can expand as much as they want vertically (
stackblitz here
Problem:
How to automatically set the width of the row elements? Here I simply put a value that looks good: width:200px.
I want them to have a width dependent on the number of element per row.
What I tried:
Using elementRef in Horizontile (component holding the individual tiles, displaying with *ngFor) to get the width of this element:
currentWidth:number;
constructor(private el:ElementRef) {}
ngAfterViewInit(): void {
this.currentWidth=this.el.nativeElement.offsetWidth;}
it returns 5. (??) Using .width returns nothing. Also this is not recommended, I'd like another solution, less coupling.
I noticed I can make use of width:inherit; in the css of the individual tile component, which allows me to set the style from the horizontal list component.
<app-tile [style.width.px]="0.9*currentWidth/nDisplayedTiles" [tile]="item"></app-tile>
As the currentWidth value is zero, of course it doesn't work;
I tried setting it in % but the inherits css tag keeps the %, which is not the intended effect.
Why is the app-tile styling not cared about if inherits is not set?
I tried using ViewEncapsulation but it had no effect either.
This looks like a trivial matter though: did I just miss something?
You can use the offsetParent (link) width and create a method to return the value on each of the cells and call it in your [style.width.px], something like the following will work.
The HTMLElement.offsetParent read-only property returns a reference to the element which is the closest (nearest in the containment hierarchy) positioned ancestor element.
stackblitz
ngAfterViewInit(): void {
//added this as the compiler was throwing ExpressionChangedAfterItHasBeenCheckedError
setTimeout(() => {
this.currentWidth=this.el.nativeElement.offsetParent.clientWidth;
});
}
getWidth(): number{
let width:number = 0;
//you may need to change this value to better display the cells
let multiplier = 0.7;
width = (this.currentWidth * multiplier) / this.ndisplayTiles;
width = Math.round(width);
return width;
}
<app-tile [class]="'layout-tile'" [tile]="item" [style.width.px]="getWidth()">
</app-tile>

Pure CSS parallaxing (not fixed) background for single row in layout

I'm wondering if it's possible to use only CSS to create a parallax scrolling background that meets the following specifications.
It works on an element that sits inside an otherwise static layout (i.e. my whole page layout isn't a group of parallaxing items)
The background isn't entirely fixed in place; it moves, just not as fast as the rest of the page.
I've looked up tons of tutorials for parallaxing backgrounds, and have found some seemingly great tutorials, but they all have one of the following problems.
They rely on the whole page being a parallax group so that you're actually scrolling over a container via an "overflow: auto" specification
The background is totally fixed in place
they use JavaScript.
Sooo, I can accomplish what I want with JavaScript fairly easily. Here's a full working example on JSFiddle that you can try out.
CSS
.parallax-row {
background-image: url(http://lorempixel.com/output/nature-q-c-781-324-3.jpg);
background-size: auto 150%;
}
JavaScript
/**
* Update the parallaxing background img to partially scroll
*/
jQuery(document).ready(function($) {
$(window).on('scroll', function() {
$('.parallax-row').each(function(index, el) {
var $el = $(el);
var fromTop = $el.offset().top + ($el.outerHeight() / 2) - $(window).scrollTop();
var windowHeight = $(window).height();
var percent = (fromTop * 100 / windowHeight);
$el.css('background-position', '0 ' + percent + '%');
});
});
});
Is it possible to accomplish that same effect with just CSS?

Infinity.js - Issues with rendering inline-block elements & a grandpa container with defined height

I've been trying to integrate infinity inside a defined scrolled area.
My UI is a bunch of inline-block thumbnails (not floated). Grid Layout.
Infinity works perfect inside my page when it occupy the whole page width & height, and each element is block level, with simple DOM inside.
But when create a little more advanced UI, with grid interface, and an infinity area to scroll inside a container (ListView's height isn't defined. It's container does), then all gets wrong.
Even more than that. If I give 100% to HTML & Body, infinity fails. it calculates wrong listView`s height.
How to solve this? Grid UI is a desired & common one.
JS Fiddle Demos:
All 1300 elements are block-level - #OK
ListItem (CSS) Width & Height defined - #OK
ListItem as inline-block - #Broken
Code Example (Infinity NG Integration)
var demoApp = angular.module("demo", []);
demoApp.controller("demoCtrl", function($scope) {
$scope.items = [];
for(var i = 0; i < 1300; i++) {
$scope.items.push({ title: "Item " + i });
}
});
demoApp.directive("infinityScroll", function() {
'use strict';
return {
restrict: "A",
transclude: true,
link: function(scope, elm, $attrs) {
scope.listView = new infinity.ListView($(elm));
}
};
});
demoApp.directive("infinityItem", function() {
'use strict';
return {
restrict: "A",
link: function(scope, element, attrs) {
scope.listView.append(element);
}
}
});
PostScript: I noticed in the API Reference, that ListItem has width & Height properties. Same as ListView.
I couldn't find how to implement it, Inside the build code itself, i haven't seen how to pass this properties to the object.
Sorry if its obvious thing, and its possible to do that.
Will appreciate any help.
Thanks.
Actually right now I discovered my problem.
2 elements that messed up with my UI where actually - Overflow:Hidden for my Body,HTML, and Height:100% for a page container.
I have removed Overflow:Hidden, and Height from the page container (not ListView!) and all is fine.
'useElementScroll:true' and .scrollable classname did not assisted me, and prevented me from needing do this actions.
Now my UI is impacted, and I need to see how I`ll solve it.
Edit:
I have opened an issue at airbnb git, and I hope they will pay attention to this. Not been able to set a father and relate only to him, is an issue that adds complexity.
https://github.com/airbnb/infinity/issues/46

Rotate background-image in a rotated div?

I have a div shape with before: and after: so it looks like a cross shape (Rotated).
But now my problem is, that the background is logically also rotated. I'd like that the background image isn't rotated and the image should be the size of the div.
I already tried to add a transform rotate to the place where I added the background but it didnt rotate back. Also for the size I tried background-size to adjust it, didnt work either.
Here is my jsbin: http://jsbin.com/iYogaCE/29/edit
thanks in advance!
nick
Well, I tried for a while to get a version working with pure CSS and HTML, but I was unable to do so. I believe that double pseudo selectors, aka ::after and ::before, would allow it to be possible, but I don't think that you can do it in pure CSS in one object currently.
With that being said, the way I accomplished it using one element is the much more common way - by using a canvas. With canvas it becomes pretty simple. Hopefully the comments make it easy to understand
Live demo here
// Gets a list of all the canvases to create an X for
var canvases = document.getElementsByClassName('profile');
// Allows the X to be drawn on multiple canvases without being redrawn
var tempCanvas = drawX();
// Gives the canvases a background image (the person's profile)
// If you wanted different images for each you could easily create an array
// and iterate through it for each canvas
var background = new Image();
background.src = "http://asta-design.ch/gameotion/wp-content/uploads/2013/03/placeholder.jpg";
// Once the image has loaded, apply the Xs
background.onload = function() {
// Do it for each canvas
for(var i = 0, j = canvases.length; i < j; i ++)
{
// Gets the current canvas and context
var canvas = canvases[i];
var context = canvas.getContext('2d');
// Allows the portrait only to be shown through the generated X
context.globalCompositeOperation = "destination-atop";
// Draws the profile picture
context.drawImage(background, 0,0, canvas.width, canvas.height)
// Cuts out everything that is not within the X
context.drawImage(tempCanvas, 0, 0);
}
}
// Creates the X to use as the cut out
function drawX() {
// Creates a hidden canvas to draw the X on
var offscreenCanvas = document.createElement('canvas');
var offscreenCtx = offscreenCanvas.getContext('2d');
// The width/height of the original canvas, not sure why "canvas.width" doesn't work here...
var size = 200;
offscreenCanvas.width = size;
offscreenCanvas.height = size;
// Creates the rectangles sloped positively
offscreenCtx.save();
offscreenCtx.translate(3 * size / 4, 3 * size / 4);
offscreenCtx.rotate(Math.PI/4);
offscreenCtx.fillRect(-size/2, -size/2, size * .3, size);
// Loads the state before the first rectangle was created
offscreenCtx.restore();
// Creates the rectangles sloped positively
offscreenCtx.translate(3 * size / 4, 1 * size / 4);
offscreenCtx.rotate(-Math.PI/4);
offscreenCtx.fillRect(-size/2, -size/2, size * .3, size);
// Returns the canvas with the X
return offscreenCanvas;
}
You can't rotate a CSS background independently of the element it is attached to.
The only way you're going to be able to do this is to have the rotated content in an additional element inside your existing one, and only rotate the inner element.
eg:
<div> <-- background applied to this element
<div>....</div> <-- but this one is rotated
</div>
Now your background will remain static while the content inside it rotates.
If you can't have any extra markup, you could still achieve this without changing the HTML, by using CSS the :before selector to create an additional pseudo-element behind the main element. Apply the background to that instead of the main element; after that it's similar to what I described above with the extra markup.
Hope that helps.

is it even possible to expand a (horizontal) list's background with ajax?

I've got a list with list-style-none which needs to be able to add new items to itself via Ajax and have the background expand appropriately when it does. Adding via Ajax is easy, but every solution I try for the background fails me. I don't know if it's even possible; is it? I'm using a grid like this one:
http://jqueryui.com/demos/sortable/#display-grid
Both WebKit and Firebug are showing me skinny, empty bars when I hover over the enclosing divs and/or the enclosing ul tag. It appears that the minute you set a list loose with list-style-none and float:wherever, you give up control over its background. But that can't be right.
This is something I've run into a number of times. The problem is that floated elements aren't part of the normal box model, so they don't cause their parent elements to expand unless their parent elements are also floated. So if possible, float the ul or containing div.
Edit:
See quirksmode for another css-only workaround.
Could you provide a sample of your code? Also, why does the list have display:none set?
For instance, should be as simple as this:
HTML:
<ul id="dest"></ul>
JS:
// Simplified example, most likely wrapped in $.ajax
// This is the AJAX response function
function(data, response) {
var items = json.parse(data);
$.each(items, function() {
// Assumes item has a name property
$('#dest').append($('<li>' + this.name + '</li>'));
});
}
Should be just that simple. You shouldn't need the hide the list initially, as you can simply append list items and have the display update appropriately.
Hope that helps.
You need to explicitly set the width and height for the area.
Check out this link for Horizontal Scrolling: http://valums.com/scroll-menu-jquery/
Here is the script:
$(function(){
//Get our elements for faster access and set overlay width
var div = $('div.sc_menu'),
ul = $('ul.sc_menu'),
// unordered list's left margin
ulPadding = 15;
//Get menu width
var divWidth = div.width();
//Remove scrollbars
div.css({overflow: 'hidden'});
//Find last image container
var lastLi = ul.find('li:last-child');
//When user move mouse over menu
div.mousemove(function(e){
//As images are loaded ul width increases,
//so we recalculate it each time
var ulWidth = lastLi[0].offsetLeft + lastLi.outerWidth() + ulPadding;
var left = (e.pageX - div.offset().left) * (ulWidth-divWidth) / divWidth;
div.scrollLeft(left);
});
});
Basically, you need to update the ulWidth and divWidth when you add the new item.
Then just set the background image to repeat horizontally and you should be set.
ul.sc_menu {background:transparent url(image.png) repeat scroll 0 0;height:100px}
Note: You will need to set the height; otherwise you will not see the background because the li are floated.
For dealing with the float element, maybe you should know it's characteristic, gotcha, and how to deal with it.
See the links below, it also have demo, so you can understand the concept:
http://www.smashingmagazine.com/2009/10/19/the-mystery-of-css-float-property/
http://www.smashingmagazine.com/2007/05/01/css-float-theory-things-you-should-know/
http://aloestudios.com/2009/12/goodbye-overflow-clearing-hack/
and
http://aloestudios.com/misc/overflow/

Resources