CSS Border Image: rendering a frame by rotating an image - css

I need to render a frame (ie, a picture frame around a picture) by rotating an image:
0 degrees for the left
90 for the top
... and so on.
As far as I can tell there isn't a border-image-left|right|top|bottom property, although this would work too - please correct me if I'm wrong.
It seems I'll need to use the border-image property. Does anyone know if possible to rotate the image depending on the side?
I guess the other messy options would include
Creating four div's around the image
Manually generating a frame border image (this won't really work as 1. we've got over 300 images, and 2. the frames need to be used on images with different aspect ratios... )
Edit: 'depending on the side' = 0 degrees for left, 90 degrees for top, 180 degrees for right, 240 for bottom... See image below for an example.
Left hand border image

Partially forced, but wrapping it in a div and span and playing with pseudo elements and transforms seemed to work.
The image is wrapped in an .img-container div and a span, and the ::before and ::after elements are absolute positioned around the image.
Here's the markup:
<div class="img-container">
<span>
<img src="https://unsplash.it/300/300?image=200">
</span>
</div>
And the styling:
.img-container, span, img{
display: block;
position: relative;
}
/* Image border general */
.img-container::before,
.img-container::after,
span::before, span::after{
content: "";
position: absolute;
left: -30px;
top: 50%;
width: 30px;
height: 100%;
transform: translateY(-50%);
background-image: url("https://i.stack.imgur.com/0UI1w.png");
background-size: 100% 100%;
z-index: 2;
}
/* Specific to the right border */
.img-container::after{
left: auto;
right: -30px;
top: 50%;
transform: translateY(-50%) rotate(180deg);
}
/* Top and bottom border general */
span::before,
span::after{
top: 0;
left: 50%;
transform: translate(-50%, -50%) rotate(90deg);
}
/* Just the bottom */
span::after {
top: 100%;
left: 50%;
transform: translate(-50%, -50%) rotate(270deg);
}
May be a little much
Here's a fiddle

Related

How to center an image overlaid on a div *but* have the image centered by its bottom rather than its center?

I'm new to CSS and a bit stuck on how to modify my CSS to fix this issue.
So I have some code that is working for the most part. I have a div containing (simplified):
<div id="map">
<div id="mapContainer"/>
<img id="iconOnMap" src="pinSource"/>
</div>
And basic CSS placing the image in the center of the mapContainer div:
#iconOnMap {
width: 2em;
height: 2em;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
position: absolute;
z-index: 1;
}
#map {
width: 95vw;
height: 55vw;
position: relative;
}
#mapContainer {
position: absolute;
width: inherit;
height: inherit;
}
However, the image is centered in the div at its center, whereas, I want the bottom of the image to be at the center, not the center of the image to be at the center.
An illustration of the issue:
In the image above, the blue marker is pointing to the correct location and the red pin indicates the incorrect behavior. Whereas the pin's middle is where the center currently is, the pin's bottom / pinpoint should be at the center instead. Any tips on how to accomplish this?
It's in the middle because you're telling it to be in the middle. Instead of:
#iconOnMap {
...
transform: translate(-50%, -50%);
...
}
Try:
#iconOnMap {
...
transform: translate(-50%, -100%);
...
}
That should translate it in the Y direction by the icon's full height instead of half its height.

position css arrow half way down div

I have a css arrow positioned at the size of my div.
Here is a jsbin that shows it in action.
How can I position the arrow half way down the div no matter what height the div is?
When you use position: absolute you can center things like this:
position: absolute;
top: 50%;
transform: translateY(-50%);
top: 50% assigns 50% of the parent's height to top
transform: translateY(-50%) moves the element up by 50% of the element's height.
This method works regardless of the element's height or the parent's height.
You can also use it to center things horizontally:
position: absolute;
left: 50%;
transform: translateX(-50%);
or both vertically and horizontally:
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
http://jsbin.com/lixisidezu/1/edit?html,css,output
I'd do it by changing the way you calculate top, so in this case using "calc" and by subtracting border-width.
top: calc(50% - 10px)
Here is a working jsbin.
You don't actually need CSS3 for this; CSS2 suffices and without too much hackishness: http://jsbin.com/civijuvofo/1/edit?html,css,output - the essence is to do e.g. top: 50%; margin-top: -10px;.
In particular, you can position the white+gray triangles half-way down box with top: 50%;. Then they're too low - they start at the 50% midpoint, but they descend down to 50% + 2*borderwidth. You could use css3 calc to compensate, or a css3 transform, but the most compatible hack is simply to apply a negative top margin equal to the border width.
That means your "arrow" fan-out then looks as follows in CSS:
.container:before, .container:after {
content: '';
display: block;
position: absolute;
top: 50%;
right: 100%;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
}
.container:before {
margin-top: -11px;
border-width: 11px;
border-right-color: #dedede;
}
.container:after {
margin-top: -10px;
border-width: 10px;
border-right-color: #fff;
}
This 'll work cross-browser in pretty much any browser released in the past 10-15 years. I'm not sure about IE7 :-).

How can I transform this div without transforming the image within?

I tried to make a shape using div and put an image inside. I want the image to maintain its default shape (rectangle or square) without skewing, but when I put image inside, the image skewed with the div. For the div shape I am using transform: skewY(-10deg);
.intro {
width: 180px;
height: 400px;
/* border-radius:50%;*/
cursor: pointer;
position: relative;
background: #fff;
transform: skewY(-10deg);
margin: 35px 35px 35px 0px;
}
.intro img {
width: 100%;
height: 100%;
}
<div class="intro">
<img src="http://lorempixel.com/180/400/sports">
</div>
You are trying to accomplish this: distort the shape of the outer object but keep the inner shape the same. The only way to do that is to transform the inner shape by the negative of the outer shape transform (aka, if your skewY(10deg) on the outer shape, do skewY(-10deg) on the inner), then hiding the overflow.
See this snippet:
.intro {
width: 180px;
height: 400px;
cursor: pointer;
position: relative;
background: #fff;
/* I added the -webkit- prefix as I'm using Safari 8 and
* it wouldn't show up otherwise. Might want to prefix that! */
-webkit-transform: skewY(-10deg);
transform: skewY(-10deg);
margin: 35px 35px 35px 0px;
overflow: hidden;
}
.intro img {
width: 100%;
height: 100%;
-webkit-transform: skewY(10deg);
transform: skewY(10deg);
}
<div class="intro">
<img src="http://lorempixel.com/180/400/sports">
</div>
An annoying sideeffect of this is that your contents will seem cut off. The only way to solve that is to make the inner shape larger than the outer shape an potentially padding the inside. For your image, I'd suggest:
.intro {
position: relative;
}
.intro img {
/* Use min width and heights higher than 100%
* (you might need to experiment here as it depends
* on the angle you chose for your skew) to fill
* the outer shape completely. */
min-width: 110%;
min-height: 110%;
/* Position the element absolute and 50%
* from the top and left */
position: absolute;
left: 50%;
top: 50%;
/* Now add a transform to it to move it with
* half of its width and height, therefore centering it. */
-webkit-transform: skewY(10deg) translate(-50%, -50%);
transform: skewY(10deg) translate(-50%, -50%);
}
Now you could also do width: 110%; height: 110%; left: -5%; top: -5%; and it would accomplish similar results. Play around with it.
Update
As per #vals suggestion, it might be a lot simpeler to just use the scale transform instead of all the positioning mumbo jumbo. Its always the simplest solution thats easiest to overlook:
.intro img {
-webkit-transform: skewY(10deg) scale(1.2, 1.2);
transform: skewY(10deg) scale(1.2, 1.2);
}

absolute position rotated element to right corner

Im trying to figure out how to make shopping cart tab that would be positioned on the right corner and also rotated 90 degrees. The rotation naturally mixes the position but maybe there's a workaround of wrapping to different wrappers etc....
Extra points if there wouldn't need to define width. I don't care about older browsers
How about using transform-origin? See DEMO.
Relevant CSS:
#box {
position: relative;
}
.bg {
right: 40px; /* same as height */
height: 40px;
transform: rotate(-90deg);
transform-origin: 100% 0;
position: absolute;
line-height: 40px; /* same as height, for vertical centering */
}
Ana's answer is excellent and pointed me in the right direction, but I realised you could achieve the same effect without having to explicitly set the height, line-height and position for the element you want to move - instead, just set translate(0, -100%):
body {
margin: 0;
}
#box {
position: relative;
}
.bg {
right: 0;
padding: 1em;
transform: rotate(-90deg) translate(0, -100%);
transform-origin: 100% 0;
position: absolute;
background: #FF1493;
}
<div id="box">
<div class="bg">
<div class="txt">He's not the Messiah. He's a very naughty boy.</div>
</div>
</div>
...and a jsFiddle for good measure.
To rotate text at 90° using CSS, consider using writing-mode.
Set position: relative; on the parent div, then use something like this on the rotated element:
#rot {
position: absolute; /* only handy here because its parent is set to `position: relative;` */
left: 0;
top: 0px;
/* writing-mode: sideways-lr; /* Webkit browsers don't support `sideways-lr` yet */
writing-mode: vertical-rl; /* `vertical-rl` and a rotation will achieve the same effect */
transform: scaleX(-1) scaleY(-1);
height: 100%;
background: rgba(0, 0, 0, 0.1);
text-align: center;
line-height: 2.85;
color: white;
font-weight: bold;
}
You'll end up with a div stacked on the side of your parent div, with the text at a 90° angle.
This way you don't have to think about the rotation origin.
If you need to position wrapper div.and rotate child div so that its always centered vertically and horizontally, try something like this!
.togglewrap{
position:relative;
float:left;left:20%;top:0;
width:30px;
height:120px;
background-color: #ffde21;
}
.sbartoggle {
background:#f5f5f5;
position:absolute;
left:0;
top:0;
right:0;
bottom:0;
margin:auto;
width:100%;
height:30px;/*equal to parent width*/
line-height:30px;/*center text*/
transform: rotate(-90deg);
background-size:10px 10px;
}

Vertically center in viewport using CSS

I am looking to vertically center a <div> in the viewport (browser window) without resorting to Javascript (pure HTML and CSS only). I have several constraints:
The div must be centered vertically in the viewport. Methods I have seen only support centering inside another <div>, which is not what I want.
The height of the div is not known.
Other constraints:
The div must be aligned to the right.
The div has a constant width.
The div must support padding.
Other elements will be placed on the web page. The div acts as a menu.
The div must support a background colour/image.
This gets me close to what I want, but not exactly:
#nav {
position: fixed;
right: 0;
top: 50%;
}
However, the top of the nav is in the middle, not the middle of the nav.
Is there some technique which allows me to center my div with these constraints?
What's that? Taking 8 years to get the answer to a problem is too much?
Well, better late than never!
You got really close to the solution. I'd do it with transform: translate():
#nav {
position: fixed;
right: 0;
top: 50%;
transform: translateY(-50%);
}
According to Can I use?, it is supported by everything except for IE8- and Opera Mini (which, to be honest, is a pretty good support).
I'd recommend you overkill it a bit and just add all of the vendor prefixes (just to make sure!):
#nav {
position: fixed;
right: 0;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
}
Here's a snippet to show it to you in action:
#nav {
right: 0;
top: 50%;
position: fixed;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
background-color: #ccc;
padding: 20px;
}
<div id="nav">
ABC<br/>
DEFGH<br/>
IJKLMNO<br/>
PQRS<br/>
TUVWXYZ
</div>
Hopefully it's still relevant to you! (who am I kidding, it's been 8 years)
you can use this as one of the solution.
<style>
#containter {
height: 100vh; //vh - viewport height
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#content {}
</style>
<div id="containter">
<div id="content">
any text<br>
any height<br>
any content, for example generated from DB<br>
everything is vertically centered
</div>
</div>
If the item is set to position: fixed or position: absolute:
top: 50%; left: 50%; transform: translate(-50%, -50%)
If the item is set to position: relative, use:
margin-top: 50%; margin-left: 50%; transform: translate(-50%, -50%)
(More info at the source.)
Example:
Run the snippet and then resize this page (or rotate device). The box stays centered in the "snippet viewport".
.myContainer {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 5px solid RebeccaPurple;
}
.myThing {
width: 100px;
height: 100px;
background-color: CornflowerBlue;
}
<div class="myContainer">
<div class="myThing myContents">
</div>
</div>
The easiest way is not to use a div - use a table with one row and one cell. Vertical alignment is woefully unsupported in CSS and you will find yourself coding up the wall and across the ceiling to accomplish it.
I understand the semantic argument against what I have just proposed - I am a proponent of semantic markup in most cases. However I also believe in using the right tool for the right job. I believe it is best to sacrifice a little purity in this case for a simple solution that will work.

Resources