Dynamic CSS 0:N Triangles in Container - css

I'm working on an Electron+Vue application that draws a grid styled map. For each cell (a room) I would like to indicate walls. For NSWE I can border-left/etc. For NW/NE/SW/SE I would like to draw an angled wall or triangle. This must be done dynamically (e.g. via classes that I inject into each cell).
There seem to be a number of ways to draw triangles and that works for a single instance or multiple if I don't need it to be dynamic. How can I do this dynamically?
Here is what I'm attempting:
<!-- ... inside a component -->
<table>
<tbody>
<tr
v-for="(row, y) in grid"
:key="y"
>
<td
v-for="(room, x) in row"
:key="x"
:class="roomClass(room)"
>
<!-- I want to conditionally add a corner triangle
in one or more corners of this cell -->
</td>
</tr>
</tbody>
</table>
// Component methods
roomClass(room) {
return {
wallseast : room.walls && room.walls.includes('southeast'),
wallswest : room.walls && room.walls.includes('southwest'),
<!-- ...so on... -->
};
},
<style scoped>
td.wallseast {
/* ??? */
}
td.wallswest {
/* ??? */
}
</style>
Update: A better example of what I'm doing. Below is a image showing a map with some walls. Note the top right (or NE) corner of one of the rooms. I would like to be able to draw this on any/all corners.

I probably wouldn't use a table... but - the concept would be the same.
You could use pseudo elements to limit the markup... and make triangles, or put an element in there... and do the border-hack trick for triangles... but I'd just use an SVG/poygon to make the triangle. You'll be just dynamically generating it, so - the extra markup is fine. It is - what it is.
You should probably have a little view component. Then have all of the triangles in there, and based on hover or game-state - give them a class or whatever to let it know what triangle to show.
<room>
<svg class='arrow ne'><polygon points='100,0 100,100 0,0'></svg>
<svg class='arrow sw'><polygon points='100,100 0,100 0,0'></svg>
<arrow class='sw'>
<!-- or if you really want... you can make the shape with CSS... -->
</arrow>
</room>
https://codepen.io/sheriffderek/pen/0cdb7ccc2efd2f1f5868380d0afae436

Did you mean something like this?
//CSS
.sq-right {
width: 201px;
height: 201px;
background-color: #fff;
transform: rotate(30deg);
position: absolute;
top: -66px;
left: -136px;
text-align: center;
}
.sq-left {
width: 201px;
height: 201px;
background-color: #fff;
transform: rotate(-30deg);
position: absolute;
top: -66px;
left: 136px;
text-align: center;
}
.bg-color{
background-color: red;
height: 172px;
width: 201px;
position: absolute;
left: 142px;
top: 106px;
text-align:center;
overflow:hidden;
}
<!-- language: lang-html -->
<div id="parentDiv">
<div class="bg-color"></div>
<div class="sq-right"></div>
<div class="sq-left"></div>
</div>
<!-- end snippet -->

So in that case you have to use SVG or canvas to create multiple triangles with the help of loop.
var canvas = document.getElementById('canvas');
if (canvas.getContext)
{
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(75,75);
context.lineTo(10,75);
context.lineTo(10,25);
context.fill();
}

Related

Why is it that adding "z-index: 1;" to the key causes this CSS piano to display incorrectly?

I've been trying to design a piano in CSS. I got it working mostly through a bunch of guessing/checking but don't understand why I had to do what I did to fix it. If I add "z-index: 1;" to the key css the sharp keys no longer overlap the white keys on their right side (even though their z-index is higher). This is not how z-index should work according to every explanation I've read. What exactly is going on here?
* {
box-sizing: border-box;
padding: 0;
margin: 0;
height:100%;
width: 100%;
}
piano {
z-index: 0;
display: flex;
position: relative;
background: black;
padding: 2px;
width: 100%;
height: 100%;
}
key {
position: relative;
background: white;
margin: 2px;
height: 100%;
width: 100%;
}
sharp {
z-index: 2;
position: absolute;
background: black;
height: 50%;
width: 50%;
right: -25%;
}
<piano>
<key #c><sharp #cs></sharp></key>
<key #d><sharp #ds></sharp></key>
<key #e></key>
<key #f><sharp #fs></sharp></key>
<key #g><sharp #gs></sharp></key>
<key #a><sharp #as></sharp></key>
<key #b></key>
</piano>
Update
"Why is it that when "z-index: 1" is added the rendering fails? Also I think it's quite common to have custom tags when working in React."
I'll address the second point first. If you use React add the React tag, don't expect anyone to know anything beyond the stated context established by the tags and the question itself.
Second point, I stated:
"Also of note that the stacking order gives higher priority to tags further down the source code, but in your case shouldn't be a problem since black keys never share the same area with each other."
This is partly my fault because I glossed over the fact you had said that z-index: 1 was set to key and the sharp to z-index: 2. It's an easy mistake since your code is the correct version not the version you had a question about. Had you added the z-index: 1 to the key and z-index: 2 to the sharp, it would've been obvious. What was the purpose of posting an example that doesn't coincide with the question?
So if you have siblings at the same z-index the tags that are positioned in the source code lower than it's "older" siblings has a higher stacking priority. (see Figure III)
Figure III
<div id='A' style='z-index:1'></div>
<div id='B' style='z-index:1'></div><!-- This will overlap anything in #A -->
<div id='C' style='z-index:1'></div><!-- This will overlap anything in #A and #B -->
Also, the example has been updated with a switch to demonstrate the problem clearly.
If you are using standard HTML (you should unless you are using a HTML preprocessor) that might help. There is no <piano>, nor are there any <key> or <sharp> elements. Use <div> and assign them ids and classes. (see Figure I & II).
Figure I - HTML
<div id="piano"><!-- id is unique, there can only be one id="piano" in a page-->
<div class='c k'><!-- class can be used multiple times on multiple elements -->
<div class='c s'></div><!-- multiple classes are space separated -->
</div>
</div>
Figure II - CSS
#piano {/*...*/} /* id is prefixed with # */
.k {/*...*/} /* class is prefixed with . */
.s {/*...*/}
Can't really tell you exactly what your problem was because you posted the correct way using z-index. Note in the example the black keys have z-index: 1. (see Introducing Z-index")
An element (aka tag) that has position: absolute (we will will refer to it as: posAbs) will position itself within the perimeter of the closest pos ancestor tag. An ancestor tag is a tag containing the tag we are referring to -- that would include any tag higher up the DOM tree. The z-index also relates to the closest pos ancestor and if none exist then it's the viewport (the entire viewable window of the browser). So if each white key is posRel and each black key is posAbs with z-index: 1 or greater will overlap all tags at index: 0 or less and "static" tags (non-pos). Also of note that the stacking order gives higher priority to tags further down the source code, but in your case shouldn't be a problem since black keys never share the same area with each other.
Anyways, the point of this answer is mainly about the use (abuse?) of HTML. HTML is forgiving and will treat non-standard tags as a <div>, but as far as how CSS and JavaScript deals with non-standard tags is unpredictable. So if you plan on actually showing your work on different browsers to anyone else in the world, then you should always practice standards.
/* For demonstration purposes only */
let keys = document.querySelectorAll('.k');
let go = document.querySelector('button');
let value = document.querySelector('b');
go.onclick = zIndex;
function zIndex(e) {
value.classList.toggle('zIndex');
keys.forEach(key => key.classList.toggle('zIndex'));
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html {
font: 300 5vmax/1 'Segoe UI'
}
#piano {
display: flex;
background: black;
}
.k {
position: relative;
z-index: auto;
width: 0.9rem;
height: 6rem;
border: 1px ridge black;
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
background: white;
}
.s {
position: absolute;
z-index: 2;
top: -2px;
right: -30%;
width: 0.6rem;
height: 3.5rem;
border: 1px ridge grey;
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
background: black;
}
/* For demonstration purposes only */
button {font:inherit;margin-left:20px}
b::before {content:'auto'}
b.zIndex::before {content:'1'}
.k.zIndex {z-index: 1}
<div id='piano'>
<div class='c k'>
<div class="c s"></div>
</div>
<div class='d k'>
<div class="d s"></div>
</div>
<div class='e k'></div>
<div class='f k'>
<div class="f s"></div>
</div>
<div class='g k'>
<div class="g s"></div>
</div>
<div class='a k'>
<div class="a s"></div>
</div>
<div class='b k'></div>
</div>
<br>
<button>GO</button> <output id='msg'>All white keys <code>index: <b></b></code></output>

Reactjs & materialize - stop fixed div when it reaches the footer

I'm working on a project, and would like to have a side panel in a fixed position on the screen (just below the navbar) until it reaches the top of the footer so the two don't overlap. I've found some suggestions using Jquery, but this project is in react and I am using the materialize css framework. Here is the code I am working with in App.js...
<div className="App">
<Navbar />
<div className="row" id="landingcontainer">
<div className="col s3" id="sidebar">
<Sidebar />
</div>
</div>
<Footer />
</div>
And here is what my css looks like:
#landingcontainer {
height: 120vh;
position: relative;
}
#sidebar {
position: fixed;
height: 85vh;
background-color: plum;
color: white;
top: 12vh;
right: 5px;
}
I've also made a sandbox for this: https://codesandbox.io/s/dawn-snow-3cmdv
Right now the when the user scrolls all the way to the bottom, the sidebar overlaps the footer.
Thanks!!
Why are you using materialize?
Just use this: https://material-ui.com/components/drawers/,
at least you'll avoid that kind of problems.
If you want to keep using materialize,
just, tell me why are you using position:fixed ?
Are you aware of that position:fixed make an element
to stay always in the same place even if the page is scrolled?
Are you sure you didn't want to do this :
#landingcontainer {
height: 120vh;
position: relative;
margin-bottom:0;
}
#sidebar {
position: absolute;
height: 100%;
background-color: plum;
color: white;
top: 0;
right: 0;
}

Give CSS property to parent td using CSS

I have referred to many options but still I am not able to apply CSS to my parent container. My table structure is like:
<td>
<div id="div1">
<div id="div2" class="colorMe"></div>
</div>
</td>
Now according to above structure if div2 has class colorMe then I want to color the entire td background in yellow.
I have used CSS like this but not working:
td > div> div.colorMe {
background-color:yellow;
}
Can you please tell me how I can color my td using css?
There is currently no possibility to apply CSS Rules to a parent element. There is in fact the :has Pseudoclass, which is exactly for this kind of issues, but at the moment (Nov 2017) it is not supported by any browser. The only way to achieve this would be with Javascript.
I know that you mentioned only using css but adding some javascript event to change a class is a very well documented approach. There are dozens of examples online and including the the script in your file takes no extra work if you use vanilla.
Here is a small example of changing a parent div's color on a click event
var box2 = document.querySelector('.color2');
box2.addEventListener("click", function() {
this.parentNode.style.backgroundColor = "white";
});
div {
width: 100px;
height: 100px;
border: 2px solid black;
}
.color1 {
background-color: red;
}
.color2 {
background-color: rebeccapurple;
width: 50px;
height: 20px;
}
<div class="color1">
<div class="color2"></div>
</div>
You can kind of emulate the behavior you need with the following trick:
td {
position: relative; /* make the cell a container for positioned children */
}
.colorMe::before { /* cover this container with colored pseudo element */
content: '';
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
background-color:yellow;
z-index: -1;
}
table { /* just to make the example prettier :) */
width: 100%;
height: 100px;
table-layout: fixed;
}
<table>
<tr>
<td>
Just a TD
</td>
<td>
<div id="div1">
<div id="div2" class="colorMe"></div>
</div>
</td>
<td>
Just a TD again
</td>
</tr>
</table>
It won't work, however, if you need to position something absolutely from the .colorMe element itself.

Place div over other elements

I'm trying to place an icon over a div but the overlaying div is pushing the rest of the contents down. I'm stuck although it should be pretty easy. Please have a look at this fiddle and let me know what I'm doing wrong (apart from using tables in the design!)
body{
background-color: #666;
}
.sizesbg {
background-color:#fff;
-webkit-border-radius: 10px;
border-radius: 10px;
width: 170px;
text-align: center;
}
.soldicon {
background: url("http://www.oroeora.gr/preowned/images/sold_curl_small.png") no-repeat scroll left top transparent;
height: 155px;
left: 0;
top: 0;
width: 170px;
z-index: 2;
}
<table>
<tr>
<td class="sizesbg">
<div style="width:150px; overflow:hidden; max-height:140px; max-width:150px; min-height:100px;">
<img src="http://www.carfolio.com/images/dbimages/zgas/manufacturers/id/843/bmw-logo.png" width="140" height="140">
</div>
</td>
<td class="sizesbg">
<div class="soldicon"></div>
<div style="width:150px; overflow:hidden; max-height:140px; max-width:150px; min-height:100px;">
<img src="http://mcurrent.name/atarihistory/warner_books_logo.gif" width="140" height="140">
</div>
</td>
<td class="sizesbg">
<div style="width:150px; overflow:hidden; max-height:140px; max-width:150px; min-height:100px;">
<img src="http://www.mindxstudio.com/images/mindxstudio-logo-icon.jpg" width="140" height="140">
</div>
</td>
</tr>
</table>
Thanks!
use position:absolute; on the divs, but of course the parent elements need to have position:relative; to stay in the right place
something like this:
http://jsfiddle.net/EESAc/5/
Edit:
This works well in Chrome ... but some other browsers had troubles (eg. Firefox), because for table elements position property is not defined, and you should use a block element instead ... so it works if you use another div around the images and set its position to relative. I added another quick fiddle for an idea:
http://jsfiddle.net/EESAc/9/
Give the class .soldicon a position: absolute; This way the element will be taken out of the document flow and won't affect the other elements.
Try to add the following to your .soldicon css:
position:absolute;
DEMO
Change your css to this:-
.soldicon {
background: url("http://www.oroeora.gr/preowned/images/sold_curl_small.png") no-repeat scroll left top transparent;
display: block;
height: 155px;
left: -7;
top: 0;
width: 170px;
z-index: 2;
position:absolute; // Change to absolute positioning
}
In my case (included popup element is bigger then including element) position: absolute;
didn't work exactly how I needed it (scrolling bar was added onto including element and the included popup wasn't displayed entirely). So the solution was:
position: fixed;

CSS - Two Divs Side by Side, One takes up as much room as need, other fills rest of width

I'm trying to get two Divs to sit side by side. I want one div to take up as much width as is needed and the other to to take up the remaining width so both divs span 100% width. Is this possible? I've tried floating and a bunch of different positioning settings but I can't find a solution that works. I naturally thought that adding a float: left to the left most element would work, however when you try to add padding/margin/border to the right element the browser wont apply it. Here is some code that I've extended (from an existing answer) to illustrate the problem.
<style>
#foo {
float: left;
background: red;
height: 100%;
padding: 5px;
}
#bar {
background: green;
border: solid 1px blue;
padding: 5px;
height: 100%;
}
</style>
<div>
<div id="foo">foo</div>
<div id="bar">bar</div>
</div>
If you open this code up in a browser you'll notice that the bar div isn't padded, and the border isn't applied to it... I have no idea why.
Thanks for any help.
This works:
<style>
#foo {
float: left;
background: red;
}
#bar {
background: green;
}
</style>
<div>
<div id="foo">foo</div>
<div id="bar">bar</div>
</div>
http://pastehtml.com/view/19ldeqq.html
why not use a table, set the whole table width to 100% and then each of the rows without a width, like so:
<table width="100%" border="0">
<tr>
<td><div>DIV INFO LEFT</div></td>
<td><div>DIV INFO RIGHT</div></td>
</tr>
</table>
This is using javascript, but it is the only way I have found to do this.
<script type="text/javascript">
window.onload = shouldNotBeThisHard;
window.onresize = shouldNotBeThisHard;
function shouldNotBeThisHard() {
var j = document.getElementById('divThatYouWantAllOf');
var k = document.getElementById('divForRestOfScreen');
var jh = 0;
if (j)
jh = j.clientWidth;
var h = (window.innerWidth - (jh + 30));
k.style.width= h + "px";
}
</script>
with the HTML looking like this:
<div id="divForRestOfScreen" style="float:left;overflow:auto;">
asdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsd
sdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsd
sdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsds
dsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsd
sdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsd
</div>
<div id="divThatYouWantAllOf" style="float:right" >
This is why I hate web programming.
</div>

Resources