Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(revision 15080)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(working copy)
@@ -217,6 +217,10 @@
 |   < FULLSTOP: "." >
 |   < DEG: "°" >
 |   < ELEMENT_OF: "∈" >
+|   < SUBSET_OR_EQUAL: "⊆" >
+|   < NOT_SUBSET_OR_EQUAL: "⊈" >
+|   < SUPERSET_OR_EQUAL: "⊇" >
+|   < NOT_SUPERSET_OR_EQUAL: "⊉" >
 |   < CROSSING: "⧉" >
 |   < PERCENT: "%" >
 |   < COMMENT_START: "/*" > : COMMENT
@@ -692,6 +696,14 @@
             |
                 <ELEMENT_OF> { type = Selector.ChildOrParentSelectorType.ELEMENT_OF; }
             |
+                <SUBSET_OR_EQUAL> { type = Selector.ChildOrParentSelectorType.SUBSET_OR_EQUAL; }
+            |
+                <NOT_SUBSET_OR_EQUAL> { type = Selector.ChildOrParentSelectorType.NOT_SUBSET_OR_EQUAL; }
+            |
+                <SUPERSET_OR_EQUAL> { type = Selector.ChildOrParentSelectorType.SUPERSET_OR_EQUAL; }
+            |
+                <NOT_SUPERSET_OR_EQUAL> { type = Selector.ChildOrParentSelectorType.NOT_SUPERSET_OR_EQUAL; }
+            |
                 <CROSSING> { type = Selector.ChildOrParentSelectorType.CROSSING; }
             )
             w()
Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(revision 15080)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(working copy)
@@ -117,7 +117,7 @@
      * @see ChildOrParentSelector
      */
     enum ChildOrParentSelectorType {
-        CHILD, PARENT, ELEMENT_OF, CROSSING, SIBLING
+        CHILD, PARENT, ELEMENT_OF, SUBSET_OR_EQUAL, NOT_SUBSET_OR_EQUAL, SUPERSET_OR_EQUAL, NOT_SUPERSET_OR_EQUAL, CROSSING, SIBLING,
     }
 
     /**
@@ -317,7 +317,6 @@
 
             protected ContainsFinder(Environment e) {
                 super(e);
-                CheckParameterUtil.ensureThat(!(e.osm instanceof INode), "Nodes not supported");
             }
 
             @Override
@@ -336,7 +335,13 @@
                 if (toCheck == null || toCheck.isEmpty())
                     return;
 
-                if (e.osm instanceof IWay) {
+                if (e.osm instanceof INode) {
+                    for (IPrimitive p : toCheck) {
+                        if (p instanceof INode && ((INode) p).getCoor().equals(((INode)e.osm).getCoor()))
+                            addToChildren(e, p);
+                    }
+
+                } else if (e.osm instanceof IWay) {
                     for (IPrimitive p : Geometry.filterInsidePolygon(toCheck, (IWay<?>) e.osm)) {
                         addToChildren(e, p);
                     }
@@ -348,6 +353,54 @@
             }
         }
 
+        private class InsideOrEqualFinder extends AbstractFinder {
+
+            protected InsideOrEqualFinder(Environment e) {
+                super(e);
+            }
+
+            @Override
+            public void visit(INode n) {
+                if (left.matches(new Environment(n).withParent(e.osm))) {
+                    if (e.osm instanceof INode) {
+                        if (n.getCoor().equals(((INode)e.osm).getCoor())) {
+                            addToChildren(e, n);
+                        }
+                    } else {
+                        if (e.osm instanceof IWay && Geometry.nodeInsidePolygon(n, ((IWay<?>) e.osm).getNodes())) {
+                            addToChildren(e, n);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void visit(IWay<?> w) {
+                if (left.matches(new Environment(w).withParent(e.osm))) {
+                    if (e.osm instanceof INode) {
+                     // not yet decided
+                    } else {
+                        if (!Geometry.filterInsidePolygon(Collections.singletonList(e.osm), w).isEmpty()) {
+                            addToChildren(e, w);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public void visit(IRelation<?> r) {
+                if (r instanceof Relation && r.isMultipolygon() && left.matches(new Environment(r).withParent(e.osm))) {
+                    if (e.osm instanceof INode) {
+                        // not yet decided
+                    } else {
+                        if (!Geometry.filterInsideMultipolygon(Collections.singletonList(e.osm), (Relation) r).isEmpty()) {
+                            addToChildren(e, r);
+                        }
+                    }
+                }
+            }
+        }
+
         @Override
         public boolean matches(Environment e) {
 
@@ -354,10 +407,11 @@
             if (!right.matches(e))
                 return false;
 
-            if (ChildOrParentSelectorType.ELEMENT_OF == type) {
+            if (ChildOrParentSelectorType.ELEMENT_OF == type || ChildOrParentSelectorType.SUBSET_OR_EQUAL == type
+                    || ChildOrParentSelectorType.NOT_SUBSET_OR_EQUAL == type) {
 
-                if (e.osm instanceof INode || e.osm.getDataSet() == null) {
-                    // nodes cannot contain elements
+                if ((ChildOrParentSelectorType.ELEMENT_OF == type  && e.osm instanceof INode) || e.osm.getDataSet() == null) {
+                    // for ELEMENT_OF nodes cannot contain elements
                     return false;
                 }
 
@@ -379,8 +433,33 @@
                     containsFinder.visit(e.osm.getDataSet().allPrimitives());
                 }
                 containsFinder.execGeometryTests();
-                return e.children != null;
+                if (ChildOrParentSelectorType.ELEMENT_OF == type || ChildOrParentSelectorType.SUBSET_OR_EQUAL == type)
+                    return e.children != null;
+                return e.children == null;
+            } else if (ChildOrParentSelectorType.SUPERSET_OR_EQUAL == type || ChildOrParentSelectorType.NOT_SUPERSET_OR_EQUAL == type) {
+                if (e.osm.getDataSet() == null || e.osm instanceof INode && ((INode)e.osm).getCoor() == null) {
+                    return false;
+                }
 
+                InsideOrEqualFinder insideOrEqualFinder = new InsideOrEqualFinder(e);
+                e.parent = e.osm;
+
+                if (left instanceof OptimizedGeneralSelector) {
+                    if (((OptimizedGeneralSelector) left).matchesBase(OsmPrimitiveType.NODE)) {
+                        insideOrEqualFinder.visit(e.osm.getDataSet().searchNodes(e.osm.getBBox()));
+                    }
+                    if (((OptimizedGeneralSelector) left).matchesBase(OsmPrimitiveType.WAY)) {
+                        insideOrEqualFinder.visit(e.osm.getDataSet().searchWays(e.osm.getBBox()));
+                    }
+                    if (((OptimizedGeneralSelector) left).matchesBase(OsmPrimitiveType.RELATION)) {
+                        insideOrEqualFinder.visit(e.osm.getDataSet().searchRelations(e.osm.getBBox()));
+                    }
+                } else {
+                    // use slow test
+                    insideOrEqualFinder.visit(e.osm.getDataSet().allPrimitives());
+                }
+                return ChildOrParentSelectorType.SUPERSET_OR_EQUAL == type ? e.children != null : e.children == null;
+
             } else if (ChildOrParentSelectorType.CROSSING == type && e.osm instanceof IWay) {
                 e.parent = e.osm;
                 if (right instanceof OptimizedGeneralSelector
