css skew multiple elements keeping images and text straight [duplicate] - css

Is it possible to reproduce this image using only CSS?
I want to apply this to my menu, so the brown background appears on hover instance
I don't know how to do this, I only have;
.menu li a:hover{
display:block;
background:#1a0000;
padding:6px 4px;
}

skew a parent element (li in this example) and inverse skew its child elements:
nav ul {
padding: 0;
display: flex;
list-style: none;
}
nav li {
transition: background 0.3s, color 0.3s;
transform: skew(20deg); /* SKEW */
}
nav li a {
display: block; /* block or inline-block is needed */
text-decoration: none;
padding: 5px 10px;
font: 30px/1 sans-serif;
transform: skew(-20deg); /* UNSKEW */
color: inherit;
}
nav li.active,
nav li:hover {
background: #000;
color: #fff;
}
<nav>
<ul>
<li>Home</li>
<li class="active">Products</li>
<li>Contact</li>
</ul>
</nav>

Here is a fiddle for use across different browsers - I created in a couple of minutes.
Try playing with the arguments, I used :before and :after to do this.
https://jsfiddle.net/DTBAE/

You can use the transform: skew(X, Y) property to achieve this. Creating a skewed outer container, then skew the opposite amount on an inner container to skew the text back to being straight. See this fiddle for example;
http://jsfiddle.net/UZ6HL/4/
From what you have said, I believe this is what you want, if not please clarify when the item should display the background.

.skew {
background: green;
color: #fff;
padding: 50px;
transform: skewX(-7deg);
font-size: 20px;
font-weight: 700;
}
.skew p {
transform: skewX(7deg);
}
<div class="skew">
<p>This is caption</p>
</div>
Here's an example

To have IE support just add -ms-transform: skew(20deg, 0deg); beside all the other transform: skew(20deg, 0deg);s.

NOTE: SPAN is NOT affected by transform CSS functionality, so you will need a DIV or change span to display: block; otherwise they will NOT be affected.
So just put the TEXT inside a separate div and unskew it.
example wrapper div is:
transform: skewx(35deg)
but text div is:
transform: skewx(-35deg);
here is codepen: https://codepen.io/dmitrisan/pen/NWaYEzV

You can use clip-path to make results like these.
For example:
* {
box-sizing: border-box;
}
body {
padding: 0;
margin: 0;
}
ul {
display: flex;
width: 100%;
flex-direction: row;
gap: 20px;
background: #000;
padding: 0 10px;
justify-content: flex-end;
}
li {
list-style-type: none;
clip-path: polygon(20% 0%, 100% 0, 80% 100%, 0% 100%);
background: blue;
padding: 10px 50px;
}
a {
color: #fff;
}
<ul>
<li>Home</li>
<li>About</li>
</ul>
You can generate your clip from here and use it in your code.
Here is a working Fiddle for reference

Related

How to make pseudo-element follow text across line break?

I've created CSS for anchor text that transitions a background-color and a border-bottom using opacity. (This is done to meet the Chrome Lighthouse auditor's spec on avoiding transitions except on compositor-only effects.)
The CSS puts the transitioned items on a ::before pseudo-element built on the anchor. Notice that the pseudo-element is absolutely positioned, which is a requirement of the technique as currently constructed. It works except when the anchor text follows a line break. A working, illustrated example is provided on this CodePen.
The CSS and HTML are also provided here:
* {
margin: 0;
padding: 0;
}
body {
margin: 1em;
font-size: 24px;
line-height: 1.5;
}
header,
article {
display: inline-block;
margin: 1em;
width: 100%;
}
p {
padding-bottom: 1em;
}
ul {
list-style: none;
}
li {
float: left;
margin-right: 1em;
}
a {
background-color: transparent;
border-bottom-color: transparent;
border-bottom-style: solid;
color: blue;
text-decoration: none;
position: relative;
}
a::before {
background-color: lightgray;
border-bottom-color: blue;
border-bottom-style: solid;
content: '';
opacity: 0;
transition: opacity 500ms ease;
position: absolute;
top: -5px;
left: 0;
bottom: -5px;
right: 0;
z-index: -1;
}
a:hover::before {
opacity: 1;
}
a::after {
--icon-width: 24px;
color: blue;
content: '';
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImJsdWUiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWV4dGVybmFsLWxpbmsiPjxwYXRoIGQ9Ik0xOCAxM3Y2YTIgMiAwIDAgMS0yIDJINWEyIDIgMCAwIDEtMi0yVjhhMiAyIDAgMCAxIDItMmg2Ij48L3BhdGg+PHBvbHlsaW5lIHBvaW50cz0iMTUgMyAyMSAzIDIxIDkiPjwvcG9seWxpbmU+PGxpbmUgeDE9IjEwIiB5MT0iMTQiIHgyPSIyMSIgeTI9IjMiPjwvbGluZT48L3N2Zz4=);
margin-left: 0.2em;
padding-left: var(--icon-width);
background-size: var(--icon-width) var(--icon-width);
background-position: center center;
background-repeat: no-repeat;
z-index: 999;
}
<body>
<header>
<ul>
<li><a href=#>Anchor 1</a></li>
<li><a href=#>Anchor 2</a></li>
<li><a href=#>Anchor 3</a></li>
</ul>
</header>
<article>
<h1>Composited transitions on border-bottom and background-color</h1>
<p>Avoid non-composited transitions! <code>opacity</code> and <code>transform</code> transitions are preferred by the Lighthouse auditor.</p>
<p>See: Stick to Compositor-Only Properties and Manage Layer Count by
Paul Lewis of Google.</p>
<p>Hover over the links to see the <code>border-bottom</code> and <code>background-color</code> fade in to cover the link text fully. This method works so long as the anchor text does not wrap across lines.</p>
<p><strong><em>Resize the window until the long link text on the line above this one wraps to a second line. At that point, the technique fails.</em></strong></p>
<p>Can you see a solution for the CSS?</p>
</article>
</body>
How would I edit the CSS so that the ::before element follows the line break of the anchor text?

why the class for h4 tag don't work probably [duplicate]

Is it possible to reproduce this image using only CSS?
I want to apply this to my menu, so the brown background appears on hover instance
I don't know how to do this, I only have;
.menu li a:hover{
display:block;
background:#1a0000;
padding:6px 4px;
}
skew a parent element (li in this example) and inverse skew its child elements:
nav ul {
padding: 0;
display: flex;
list-style: none;
}
nav li {
transition: background 0.3s, color 0.3s;
transform: skew(20deg); /* SKEW */
}
nav li a {
display: block; /* block or inline-block is needed */
text-decoration: none;
padding: 5px 10px;
font: 30px/1 sans-serif;
transform: skew(-20deg); /* UNSKEW */
color: inherit;
}
nav li.active,
nav li:hover {
background: #000;
color: #fff;
}
<nav>
<ul>
<li>Home</li>
<li class="active">Products</li>
<li>Contact</li>
</ul>
</nav>
Here is a fiddle for use across different browsers - I created in a couple of minutes.
Try playing with the arguments, I used :before and :after to do this.
https://jsfiddle.net/DTBAE/
You can use the transform: skew(X, Y) property to achieve this. Creating a skewed outer container, then skew the opposite amount on an inner container to skew the text back to being straight. See this fiddle for example;
http://jsfiddle.net/UZ6HL/4/
From what you have said, I believe this is what you want, if not please clarify when the item should display the background.
.skew {
background: green;
color: #fff;
padding: 50px;
transform: skewX(-7deg);
font-size: 20px;
font-weight: 700;
}
.skew p {
transform: skewX(7deg);
}
<div class="skew">
<p>This is caption</p>
</div>
Here's an example
To have IE support just add -ms-transform: skew(20deg, 0deg); beside all the other transform: skew(20deg, 0deg);s.
NOTE: SPAN is NOT affected by transform CSS functionality, so you will need a DIV or change span to display: block; otherwise they will NOT be affected.
So just put the TEXT inside a separate div and unskew it.
example wrapper div is:
transform: skewx(35deg)
but text div is:
transform: skewx(-35deg);
here is codepen: https://codepen.io/dmitrisan/pen/NWaYEzV
You can use clip-path to make results like these.
For example:
* {
box-sizing: border-box;
}
body {
padding: 0;
margin: 0;
}
ul {
display: flex;
width: 100%;
flex-direction: row;
gap: 20px;
background: #000;
padding: 0 10px;
justify-content: flex-end;
}
li {
list-style-type: none;
clip-path: polygon(20% 0%, 100% 0, 80% 100%, 0% 100%);
background: blue;
padding: 10px 50px;
}
a {
color: #fff;
}
<ul>
<li>Home</li>
<li>About</li>
</ul>
You can generate your clip from here and use it in your code.
Here is a working Fiddle for reference

How to make the text inside div stick to the left?

I have setup a list of tags inside an unordered list. I want this component to house a vertically aligned items on the side of the page.
It currently looks like below:
Here's how the sidebar is currently setup:
export default class SideBar extends PureComponent {
render() {
return (
<div className="sidebar-container">
<ul class="sidebar-list">
<li role="presentation" class="active">Home</li>
<li role="presentation">Profile</li>
<li role="presentation">Messages</li>
</ul>
</div>
);
}
}
with css
.sidebar-container {
position: absolute;
left: 0;
top: 0;
bottom: 0;
flex-shrink: 1;
z-index: 999;
// width: 20px;
}
.sidebar-container > ul {
list-style: none;
}
.sidebar-list > li {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
-webkit-writing-mode: vertical-lr;
-ms-writing-mode: tb-lr;
writing-mode: vertical-lr;
// background-color: pink;
color: white;
}
.sidebar-list > li > a {
color: red;
text-decoration: none;
text-transform: uppercase;
margin-top: 16px;
background-color: green;
font-size: 5vh;
}
How can I stick it to the left?
Browsers give uls a default padding (Chrome for example gives it 40px). You need to set that to 0 like this:
.sidebar-container > ul {
list-style: none;
padding: 0;
}
If I'm understanding correctly, couldn't you just used fixed?
.sidebar-container {
position: fixed;
top: 0;
left: 0;
}
It will be removed from the flex flow (I believe) so you might need to adjust some other bits and bobs based on that.
ul has default padding you need to override it.
See here. http://jsfiddle.net/bhupendra_nitt/1dxt36sb/6/
If you have not got a browser reset in your project you should do. Use normalize
https://necolas.github.io/normalize.css/ or something similar. Most of these issues will not be present for you after but I as everyone has said you need to remove the default padding from the ul

How to target text inside an html element?

I have the following case generated by a plugin which I am not able to rewrite as I would need to fix this. It generates breadcrumbs for a website like the following example:
<li><a>Parent</a></li>
<li><a>Subparent</a></li>
<li><a>Subsubparent</a></li>
<li>Current Site</li>
I have styled the links to be clickable more easy
li {height: 40px;}
li a {padding: 5px; display: inline-block; height: 30px;}
Now of course the last element does not get the same padding and looks wired. I am not able to wrap a html element like span around it in php.
Is there a css selector to select the text inside of an element, without affecting the element itself? Or wraps an html element like span around it, something like
li:last-child::before {content:"<span>"}
Every hint appreciated! If someone likes jsfiddle here is one to play with.
Why don't you just add the padding to the last li together with the anchors?
Updated JsFiddle
li a, li:last-child {padding: 10px; display: inline-block;}
I have created the following work-around to get the right styling.
li:last-child::before {
content: "";
opacity: 0;
display: inline-block;
margin: 10px 0 10px 10px;
}
li:last-child::after {
content: ".";
opacity: 0;
display: inline-block;
margin: 10px 10px 10px 0;
}
Sadly one of the both pseudo elements needs content:"." or another real content. This is a solution to target spacing (margin/padding) without changing some css/html.
Updated jsfiddle
Still I would love to see clean css solutions!
My own suggestion, at its simplest, would be:
li {
height: 40px;
/* vertically-aligns the text to
the same 'line': */
line-height: 40px;
/* to display in a row, given the
text-alignment I assume this is required,
remove/adjust if not: */
float: left;
/* removes the bullets: */
list-style-type: none;
/* Just to clearly show the size of
the <li> elements: */
background-color: #ffa;
}
li:nth-child(odd) {
/* again, just to show the size: */
background-color: #f90;
}
li a {
/* to fill the whole of the <li>: */
display: block;
}
li a:hover {
/* just to show the hover 'hit-area': */
background-color: #f00;
transition: background-color 0.4s linear;
}
li {
height: 40px;
line-height: 40px;
float: left;
list-style-type: none;
background-color: #ffa;
}
li:nth-child(odd) {
background-color: #f90;
}
li a {
display: block;
}
li a:hover {
background-color: #f00;
transition: background-color 0.4s linear;
}
<ul>
<li>Parent
</li>
<li>Subparent
</li>
<li>Subsubparent
</li>
<li>Current Site</li>
</ul>
Now, to style them as 'breadcrumbs,' you could use generated content to provide
the separators, for example, you can update the CSS:
li {
/* other rules remain the same,
this is added to provide space
for the generated content: */
margin-left: 1em;
}
/* there is (usually) no marker before
the first breadcrumb, this removes its
space: */
li:first-child {
margin-left: 0;
}
/* other rules that, remain the
same, are excised for brevity */
li::before {
/* unicode for the guillemot,
'ยป', character: */
content: '\00BB';
/* to position easily and prevent
altering the position of the child
<a> elements: */
position: absolute;
/* simple means to move the generated
content off the left edge: */
right: 100%;
width: 1em;
text-align: center;
}
/* no marker the first breadcrumb: */
li:first-child::before {
/* removing both content and width: */
content: '';
width: 0;
li {
height: 40px;
line-height: 40px;
position: relative;
margin-left: 1em;
float: left;
list-style-type: none;
}
li:first-child {
margin-left: 0;
}
li a {
display: block;
}
li a:hover {
background-color: #f00;
transition: background-color 0.4s linear;
}
li::before {
content: '\00BB';
position: absolute;
right: 100%;
width: 1em;
text-align: center;
}
li:first-child::before {
content: '';
width: 0;
}
<ul>
<li>Parent
</li>
<li>Subparent
</li>
<li>Subsubparent
</li>
<li>Current Site</li>
</ul>

How can I use CSS3 transform on a span?

I have an inline element (a <span>) nested in a <h1> tag. I applied a transform property to the h1 ( skew so it looks like a parallelogram).
I need to transform the <span> tag to "unskew" it and its text. But this only seems to work in IE.
Here is an example of the HTML and CSS:
h1 {
background: #f00;
padding: .25em .5em;
text-align: right;
transform: skew(-15deg);
}
h1 span {
color: #fff;
transform: skew(15deg);
}
<h1><span>This is a Title</span></h1>
Explanation:
A <span> or a link (<a>) are inline elements and the transform property doesn't apply to inline elements.
Here is the list of transformable elements from the CSS Transforms Module Level 1.
Solution:
Set the display property of the span to inline-block or block. This will let you apply transforms to the span element.
It also works for other inline elements like <a> <em> <strong>... (see the list of inline elements on MDN).
Here is a demo with the <span> and link <a> elements :
h1 {
background: teal;
padding: .25em .5em;
margin: 1em;
transform: skew(-15deg);
}
h1 span,
h1 a {
color: #fff;
display: inline-block; /* <- ADD THIS */
transform: skew(15deg);
}
<h1><span>This is a span in a title</span></h1>
<h1>This is a link in a title</h1>
A little late here, but you can set
h1 span{
position:absolute;
}
Then use the CSS3 transform properties normally. Demo:
h1 {
background: #f00;
padding: .25em .5em;
text-align: right;
transform: skew(-15deg);
height: 40px;
}
h1 span {
position: absolute;
left: 20px;
color: #fff;
transform: skew(15deg);
}
<h1><span>This is a Title</span></h1>

Resources